Adding sensitivity experiment.
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / ConversationPair.java
1 package edu.uci.iotproject;
2
3 import org.pcap4j.core.PcapHandle;
4 import org.pcap4j.core.PcapPacket;
5
6 import java.io.FileNotFoundException;
7 import java.io.PrintWriter;
8 import java.io.UnsupportedEncodingException;
9 import java.util.HashMap;
10 import java.util.Map;
11
12 /**
13  * Models a (TCP) conversation/connection/session/flow (packet's belonging to the same session between a client and a
14  * server).
15  * Holds a pair of packet lengths from {@link PcapPacket}s identified as pertaining to the flow.
16  * Here we consider pairs of packet lengths, e.g., from device to cloud and cloud to device.
17  * We collect these pairs of data points as signatures that we can plot on a graph.
18  *
19  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
20  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
21  */
22 public class ConversationPair {
23
24     /* Begin instance properties */
25     /**
26      * The PrintWriter object that writes data points into file
27      */
28     private PrintWriter pw;
29
30     /**
31      * The direction of conversation
32      * true = device to server to device
33      */
34     private Direction direction;
35
36     /**
37      * If this is the first packet processed then the value is true (it is false otherwise).
38      */
39     private boolean firstPacket;
40
41     /**
42      * Count the frequencies of points
43      */
44     private Map<String, Integer> pointFreq;
45     private String dataPoint;
46
47     /**
48      * Four possible directions of conversations.
49      * E.g., DEVICE_TO_SERVER means the conversation is started from
50      * a device-server packet and then a server-device as a response.
51      * SERVER_TO_DEVICE means the conversation is started from a
52      * server-device packet and then a device-server packet as a response.
53      * The same pattern applies to PHONE_TO_SERVER and SERVER_TO_PHONE
54      * directions.
55      */
56     public enum Direction {
57         DEVICE_TO_SERVER,
58         SERVER_TO_DEVICE,
59         PHONE_TO_SERVER,
60         SERVER_TO_PHONE
61     }
62
63     /**
64      * Constructs a ConversationPair object.
65      * @param fileName The file name to write data points into.
66      * @param direction The direction of the first packet of the pair.
67      */
68     public ConversationPair(String fileName, Direction direction) {
69         try {
70             this.pw = new PrintWriter(fileName, "UTF-8");
71         } catch(UnsupportedEncodingException |
72                 FileNotFoundException e) {
73             e.printStackTrace();
74         }
75         this.direction = direction;
76         this.firstPacket = true;
77         this.pointFreq = new HashMap<>();
78         this.dataPoint = null;
79     }
80
81     /**
82      * Writes conversation pair's packet lengths.
83      * @param packet The {@link PcapPacket} object that has packet information.
84      * @param fromClient If true then this packet comes from client, e.g., device.
85      * @param fromServer If true then this packet comes from server.
86      */
87     public void writeConversationPair(PcapPacket packet, boolean fromClient, boolean fromServer) {
88
89         // Write device data point first and then server
90         if (direction == Direction.DEVICE_TO_SERVER || direction == Direction.PHONE_TO_SERVER) {
91             if (fromClient && firstPacket) { // first packet
92                 pw.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
93                 System.out.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
94                 dataPoint = Integer.toString(packet.getPayload().length()) + ", ";
95                 firstPacket = false;
96             } else if (fromServer && !firstPacket) { // second packet
97                 pw.println(packet.getPayload().length());
98                 System.out.println(packet.getPayload().length());
99                 dataPoint = dataPoint + Integer.toString(packet.getPayload().length());
100                 countFrequency(dataPoint);
101                 firstPacket = true;
102             }
103         // Write server data point first and then device
104         } else if (direction == Direction.SERVER_TO_DEVICE || direction == Direction.SERVER_TO_PHONE) {
105             if (fromServer && firstPacket) { // first packet
106                 pw.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
107                 dataPoint = Integer.toString(packet.getPayload().length()) + ", ";
108                 firstPacket = false;
109             } else if (fromClient && !firstPacket) { // second packet
110                 pw.println(packet.getPayload().length());
111                 dataPoint = dataPoint + Integer.toString(packet.getPayload().length());
112                 countFrequency(dataPoint);
113                 firstPacket = true;
114             }
115         }
116     }
117
118     /**
119      * Counts the frequencies of data points.
120      * @param dataPoint One data point for a conversation pair, e.g., 556, 1232.
121      */
122     private void countFrequency(String dataPoint) {
123
124         Integer freq = null;
125         if (pointFreq.containsKey(dataPoint)) {
126             freq = pointFreq.get(dataPoint);
127         } else {
128             freq = new Integer(0);
129         }
130         freq = freq + 1;
131         pointFreq.put(dataPoint, freq);
132     }
133
134     /**
135      * Prints the frequencies of data points from the Map.
136      */
137     public void printListFrequency() {
138         for(Map.Entry<String, Integer> entry : pointFreq.entrySet()) {
139             System.out.println(entry.getKey() + " - " + entry.getValue());
140         }
141     }
142
143     /**
144      * Close the PrintWriter object.
145      */
146     public void close() {
147         pw.close();
148     }
149 }