add method for checking if a Conversation has been gracefully shut down.
authorJanus Varmarken <varmarken@gmail.com>
Fri, 11 May 2018 02:38:49 +0000 (19:38 -0700)
committerJanus Varmarken <varmarken@gmail.com>
Fri, 11 May 2018 02:38:49 +0000 (19:38 -0700)
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Conversation.java
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/util/PcapPacketUtils.java

index 8d5780e..f28b8fd 100644 (file)
@@ -1,5 +1,6 @@
 package edu.uci.iotproject;
 
+import edu.uci.iotproject.util.PcapPacketUtils;
 import org.pcap4j.core.PcapPacket;
 import org.pcap4j.packet.IpV4Packet;
 import org.pcap4j.packet.TcpPacket;
@@ -101,6 +102,16 @@ public class Conversation {
         mPackets.add(packet);
     }
 
+    /**
+     * Get a list of packets pertaining to this {@code Conversation}.
+     * The returned list is a read-only list.
+     * @return the list of packets pertaining to this {@code Conversation}.
+     */
+    public List<PcapPacket> getPackets() {
+        // Return read-only view to prevent external code from manipulating internal state (preserve invariant).
+        return Collections.unmodifiableList(mPackets);
+    }
+
     /**
      * Adds a TCP FIN packet to the list of TCP FIN packets associated with this conversation.
      * @param finPacket The TCP FIN packet that is to be added to (associated with) this conversation.
@@ -123,13 +134,15 @@ public class Conversation {
     }
 
     /**
-     * Get a list of packets pertaining to this {@code Conversation}.
-     * The returned list is a read-only list.
-     * @return the list of packets pertaining to this {@code Conversation}.
+     * Get if this {@code Conversation} is considered to have been gracefully shut down.
+     * A {@code Conversation} has been gracefully shut down if it contains a FIN+ACK pair for both directions
+     * (client to server, and server to client).
+     * @return {@code true} if the connection has been gracefully shut down, false otherwise.
      */
-    public List<PcapPacket> getPackets() {
-        // Return read-only view to prevent external code from manipulating internal state (preserve invariant).
-        return Collections.unmodifiableList(mPackets);
+    public boolean isGracefullyShutdown() {
+        //  The conversation has been gracefully shut down if we have recorded a FIN from both the client and the server which have both been ack'ed.
+        return mFinPackets.stream().anyMatch(finAckPair -> finAckPair.isAcknowledged() && PcapPacketUtils.isSource(finAckPair.getFinPacket(), mClientIp, mClientPort)) &&
+                mFinPackets.stream().anyMatch(finAckPair -> finAckPair.isAcknowledged() && PcapPacketUtils.isSource(finAckPair.getFinPacket(), mServerIp, mServerPort));
     }
 
     // =========================================================================================================
index 67421b8..4e57841 100644 (file)
@@ -30,4 +30,20 @@ public final class PcapPacketUtils {
         return ipSrc.equals(ip) && srcPort == port;
     }
 
+    /**
+     * Helper method to determine if the given combination of IP and port matches the destination of the given packet.
+     * @param packet The packet to check.
+     * @param ip The IP to look for in the ip.dst field of {@code packet}.
+     * @param port The port to look for in the tcp.dstport field of {@code packet}.
+     * @return {@code true} if the given ip+port match the corresponding fields in {@code packet}.
+     */
+    public static boolean isDestination(PcapPacket packet, String ip, int port) {
+        IpV4Packet ipPacket = Objects.requireNonNull(packet.get(IpV4Packet.class));
+        // For now we only support TCP flows.
+        TcpPacket tcpPacket = Objects.requireNonNull(packet.get(TcpPacket.class));
+        String ipDst = ipPacket.getHeader().getDstAddr().getHostAddress();
+        int dstPort = tcpPacket.getHeader().getDstPort().valueAsInt();
+        return ipDst.equals(ip) && dstPort == port;
+    }
+
 }