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;
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.
}
/**
- * 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));
}
// =========================================================================================================
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;
+ }
+
}