01839227e82ebeef7dca0d06c2e82d84ea86a011
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / util / PrintUtils.java
1 package edu.uci.iotproject.util;
2
3 import edu.uci.iotproject.DnsMap;
4 import edu.uci.iotproject.analysis.PcapPacketPair;
5
6 import java.util.Optional;
7 import java.util.Set;
8 import java.util.stream.Collectors;
9
10 /**
11  * Utility methods for generating (output) strings.
12  *
13  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
14  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
15  */
16 public class PrintUtils {
17
18     private PrintUtils() { /* private constructor to prevent instantiation */ }
19
20
21     /**
22      * Converts a {@code PcapPacketPair} into a CSV string containing the packet lengths of the two packets in the pair.
23      *
24      * For example, the resulting string will be "123, 456" if the first packet of the pair has a length of 123 and the
25      * second packet of the pair has a length of 456.
26      *
27      * <b>Note:</b> if the {@link PcapPacketPair} has no second element, 0 is printed as the length of the second packet
28      * in the pair.
29      *
30      * @return a CSV string containing the packet lengths of the two packets of the given {@code PcapPacketPair}.
31      */
32     public static String toCsv(PcapPacketPair packetPair) {
33         return String.format("%d, %d", packetPair.getFirst().getOriginalLength(),
34                 packetPair.getSecond().map(pp -> pp.getOriginalLength()).orElse(0));
35     }
36
37     /**
38      * Converts a {@code PcapPacketPair} into a CSV string containing the packet lengths of the two packets in the pair
39      * followed by the source of each packet. The source will be a (set of) hostname(s) if the source IP can be resolved
40      * to a (set of) hostname(s) using the provided {@link DnsMap}.
41      *
42      * For example, the resulting string will be "123, 456, 192.168.1.42, domain.com" if the first packet of the pair
43      * has a length of 123, the second packet of the pair has a length of 456, the first packet of the pair the pair has
44      * a source IP of '192.168.1.42' that cannot be resolved to a hostname, and the second packet of the pair has an IP
45      * that resolves to 'domain.com'.
46      *
47      * <b>Note:</b> if the {@link PcapPacketPair} has no second element, 0 is printed as the length of the second packet
48      * in the pair, and null is printed for its source.
49      *
50      * @return a CSV string containing the packet lengths of the two packets of the given {@code PcapPacketPair} as well
51      *         as their respective sources.
52      */
53     public static String toCsv(PcapPacketPair packetPair, DnsMap ipHostnameMappings) {
54         // First obtain source IPs
55         String firstSrc = PcapPacketUtils.getSourceIp(packetPair.getFirst());
56         // Note: use optional for second item in pair as there might not be one.
57         Optional<String> secondSrc = packetPair.getSecond().map(pkt -> PcapPacketUtils.getSourceIp(pkt));
58
59         // If possible, map source IPs to hostnames.
60         Set<String> firstHostnames = ipHostnameMappings.getHostnamesForIp(firstSrc);
61         Optional<Set<String>> secondHostnames = secondSrc.map(src -> ipHostnameMappings.getHostnamesForIp(src));
62         final String delimiter = " ";
63         if (firstHostnames != null) {
64             // If one IP maps to multiple hostnames, we concatenate the hostnames (separated by a delimiter)
65             firstSrc = firstHostnames.stream().collect(Collectors.joining(delimiter));
66         }
67         // If one IP maps to multiple hostnames, we concatenate the hostnames (separated by a delimiter)
68         Optional<String> hostnames = secondHostnames.map(hostnameSet -> hostnameSet.stream().collect(Collectors.joining(delimiter)));
69         // Fall back to IP if we couldn't second pair is present, but we couldn't map to (a) hostname(s).
70         secondSrc = hostnames.isPresent() ? hostnames : secondSrc;
71
72         return String.format("%d, %d, %s, %s", packetPair.getFirst().getOriginalLength(),
73                 packetPair.getSecond().map(pp -> pp.getOriginalLength()).orElse(0),
74                 firstSrc,
75                 secondSrc.orElse("null"));
76     }
77
78 }