Bugfix: fix null-pointer when formatting PcapPacketPairs as CSV
authorJanus Varmarken <varmarken@gmail.com>
Tue, 11 Sep 2018 23:02:09 +0000 (16:02 -0700)
committerJanus Varmarken <varmarken@gmail.com>
Tue, 11 Sep 2018 23:02:09 +0000 (16:02 -0700)
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/analysis/PcapPacketPair.java
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/util/PrintUtils.java

index db5c839c4d9028988a0a36138c0b971646733886..f77531f0f6a083629a1c5ee798170abfa58b8029 100644 (file)
@@ -1,31 +1,40 @@
 package edu.uci.iotproject.analysis;
 
 package edu.uci.iotproject.analysis;
 
+import org.apache.commons.math3.ml.clustering.Clusterable;
 import org.pcap4j.core.PcapPacket;
 
 import org.pcap4j.core.PcapPacket;
 
+import java.util.Optional;
+
 /**
  * A simple wrapper for holding a pair of packets (e.g., a request and associated reply packet).
  *
  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
  */
 /**
  * A simple wrapper for holding a pair of packets (e.g., a request and associated reply packet).
  *
  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
  */
-public class PcapPacketPair {
+public class PcapPacketPair implements Clusterable {
 
     private final PcapPacket mFirst;
 
 
     private final PcapPacket mFirst;
 
-    private final PcapPacket mSecond;
+    private final Optional<PcapPacket> mSecond;
 
     public PcapPacketPair(PcapPacket first, PcapPacket second) {
         mFirst = first;
 
     public PcapPacketPair(PcapPacket first, PcapPacket second) {
         mFirst = first;
-        mSecond = second;
+        mSecond = Optional.ofNullable(second);
     }
 
     public PcapPacket getFirst() { return mFirst; }
 
     }
 
     public PcapPacket getFirst() { return mFirst; }
 
-    public PcapPacket getSecond() { return mSecond; }
+    public Optional<PcapPacket> getSecond() { return mSecond; }
 
     @Override
     public String toString() {
 
     @Override
     public String toString() {
-        return getFirst().getOriginalLength() + ", "  + (getSecond() == null ? "null" : getSecond().getOriginalLength());
+        return String.format("%d, %s",
+                getFirst().getOriginalLength(),
+                getSecond().map(pkt -> Integer.toString(pkt.getOriginalLength())).orElse("null"));
     }
 
     }
 
+    @Override
+    public double[] getPoint() {
+        return new double[0];
+    }
 }
 }
index 75a0035e4c2ff796e5235fd3422a612b6a6f2b32..01839227e82ebeef7dca0d06c2e82d84ea86a011 100644 (file)
@@ -3,6 +3,7 @@ package edu.uci.iotproject.util;
 import edu.uci.iotproject.DnsMap;
 import edu.uci.iotproject.analysis.PcapPacketPair;
 
 import edu.uci.iotproject.DnsMap;
 import edu.uci.iotproject.analysis.PcapPacketPair;
 
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -23,11 +24,14 @@ public class PrintUtils {
      * For example, the resulting string will be "123, 456" if the first packet of the pair has a length of 123 and the
      * second packet of the pair has a length of 456.
      *
      * For example, the resulting string will be "123, 456" if the first packet of the pair has a length of 123 and the
      * second packet of the pair has a length of 456.
      *
+     * <b>Note:</b> if the {@link PcapPacketPair} has no second element, 0 is printed as the length of the second packet
+     * in the pair.
+     *
      * @return a CSV string containing the packet lengths of the two packets of the given {@code PcapPacketPair}.
      */
     public static String toCsv(PcapPacketPair packetPair) {
         return String.format("%d, %d", packetPair.getFirst().getOriginalLength(),
      * @return a CSV string containing the packet lengths of the two packets of the given {@code PcapPacketPair}.
      */
     public static String toCsv(PcapPacketPair packetPair) {
         return String.format("%d, %d", packetPair.getFirst().getOriginalLength(),
-                packetPair.getSecond().getOriginalLength());
+                packetPair.getSecond().map(pp -> pp.getOriginalLength()).orElse(0));
     }
 
     /**
     }
 
     /**
@@ -40,29 +44,35 @@ public class PrintUtils {
      * 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
      * that resolves to 'domain.com'.
      *
      * 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
      * that resolves to 'domain.com'.
      *
+     * <b>Note:</b> if the {@link PcapPacketPair} has no second element, 0 is printed as the length of the second packet
+     * in the pair, and null is printed for its source.
+     *
      * @return a CSV string containing the packet lengths of the two packets of the given {@code PcapPacketPair} as well
      *         as their respective sources.
      */
     public static String toCsv(PcapPacketPair packetPair, DnsMap ipHostnameMappings) {
      * @return a CSV string containing the packet lengths of the two packets of the given {@code PcapPacketPair} as well
      *         as their respective sources.
      */
     public static String toCsv(PcapPacketPair packetPair, DnsMap ipHostnameMappings) {
-        // First optain source IPs
+        // First obtain source IPs
         String firstSrc = PcapPacketUtils.getSourceIp(packetPair.getFirst());
         String firstSrc = PcapPacketUtils.getSourceIp(packetPair.getFirst());
-        String secondSrc = PcapPacketUtils.getSourceIp(packetPair.getSecond());
+        // Note: use optional for second item in pair as there might not be one.
+        Optional<String> secondSrc = packetPair.getSecond().map(pkt -> PcapPacketUtils.getSourceIp(pkt));
 
         // If possible, map source IPs to hostnames.
         Set<String> firstHostnames = ipHostnameMappings.getHostnamesForIp(firstSrc);
 
         // If possible, map source IPs to hostnames.
         Set<String> firstHostnames = ipHostnameMappings.getHostnamesForIp(firstSrc);
-        Set<String> secondHostnames = ipHostnameMappings.getHostnamesForIp(secondSrc);
+        Optional<Set<String>> secondHostnames = secondSrc.map(src -> ipHostnameMappings.getHostnamesForIp(src));
         final String delimiter = " ";
         if (firstHostnames != null) {
             // If one IP maps to multiple hostnames, we concatenate the hostnames (separated by a delimiter)
             firstSrc = firstHostnames.stream().collect(Collectors.joining(delimiter));
         }
         final String delimiter = " ";
         if (firstHostnames != null) {
             // If one IP maps to multiple hostnames, we concatenate the hostnames (separated by a delimiter)
             firstSrc = firstHostnames.stream().collect(Collectors.joining(delimiter));
         }
-        if (secondHostnames != null) {
-            // If one IP maps to multiple hostnames, we concatenate the hostnames (separated by a delimiter)
-            secondSrc = secondHostnames.stream().collect(Collectors.joining(delimiter));
-        }
+        // If one IP maps to multiple hostnames, we concatenate the hostnames (separated by a delimiter)
+        Optional<String> hostnames = secondHostnames.map(hostnameSet -> hostnameSet.stream().collect(Collectors.joining(delimiter)));
+        // Fall back to IP if we couldn't second pair is present, but we couldn't map to (a) hostname(s).
+        secondSrc = hostnames.isPresent() ? hostnames : secondSrc;
 
         return String.format("%d, %d, %s, %s", packetPair.getFirst().getOriginalLength(),
 
         return String.format("%d, %d, %s, %s", packetPair.getFirst().getOriginalLength(),
-                packetPair.getSecond().getOriginalLength(), firstSrc, secondSrc);
+                packetPair.getSecond().map(pp -> pp.getOriginalLength()).orElse(0),
+                firstSrc,
+                secondSrc.orElse("null"));
     }
 
 }
     }
 
 }