1 package edu.uci.iotproject;
3 import org.pcap4j.core.PcapPacket;
4 import org.pcap4j.packet.IpV4Packet;
5 import org.pcap4j.packet.TcpPacket;
7 import java.util.ArrayList;
9 import java.util.Objects;
12 * Models a (TCP) conversation/connection/session/flow (packet's belonging to the same session between a client and a
14 * Holds a list of {@link PcapPacket}s identified as pertaining to the flow. Note that this list is <em>not</em>
15 * considered when determining equality of two {@code Conversation} instances in order to allow for a
16 * {@code Conversation} to function as a key in data structures such as {@link java.util.Map} and {@link java.util.Set}.
17 * See {@link #equals(Object)} for the definition of equality.
19 public class Conversation {
21 private final String mClientIp;
22 private final int mClientPort;
23 private final String mServerIp;
24 private final int mServerPort;
25 private final List<PcapPacket> mPackets;
28 * Constructs a new {@code Conversation}.
29 * @param clientIp The IP of the host that is considered the client (i.e. the host that initiates the conversation)
30 * in the conversation.
31 * @param clientPort The port number used by the client for the conversation.
32 * @param serverIp The IP of the host that is considered the server (i.e. is the responder) in the conversation.
33 * @param serverPort The port number used by the server for the conversation.
35 public Conversation(String clientIp, int clientPort, String serverIp, int serverPort) {
36 this.mClientIp = clientIp;
37 this.mClientPort = clientPort;
38 this.mServerIp = serverIp;
39 this.mServerPort = serverPort;
40 this.mPackets = new ArrayList<>();
44 * Add a packet to the list of packets associated with this conversation.
45 * @param packet The packet that is to be added to (associated with) this conversation.
47 public void addPacket(PcapPacket packet) {
48 // Apply precondition to preserve class invariant: all packets in mPackets must match the 4 tuple that
49 // defines the conversation.
50 // ==== Precondition: verify that packet does indeed pertain to conversation. ====
51 IpV4Packet ipPacket = Objects.requireNonNull(packet.get(IpV4Packet.class));
52 // For now we only support TCP flows.
53 TcpPacket tcpPacket = Objects.requireNonNull(packet.get(TcpPacket.class));
54 String ipSrc = ipPacket.getHeader().getSrcAddr().getHostAddress();
55 String ipDst = ipPacket.getHeader().getDstAddr().getHostAddress();
56 int srcPort = tcpPacket.getHeader().getSrcPort().valueAsInt();
57 int dstPort = tcpPacket.getHeader().getDstPort().valueAsInt();
58 String clientIp, serverIp;
59 int clientPort, serverPort;
60 if (ipSrc.equals(mClientIp)) {
71 if (!(clientIp.equals(mClientIp) && clientPort == mClientPort &&
72 serverIp.equals(mServerIp) && serverPort == mServerPort)) {
73 throw new IllegalArgumentException(
74 String.format("Attempt to add packet that does not pertain to %s",
75 Conversation.class.getSimpleName()));
77 // ================================================================================
81 // =========================================================================================================
82 // We simply reuse equals and hashCode methods of String.class to be able to use this class as a key
86 * <em>Note:</em> currently, equality is determined based on pairwise equality of the elements of the four tuple
87 * ({@link #mClientIp}, {@link #mClientPort}, {@link #mServerIp}, {@link #mServerPort}) for {@code this} and
89 * @param obj The object to test for equality with {@code this}.
90 * @return {@code true} if {@code obj} is considered equal to {@code this} based on the definition of equality given above.
93 public boolean equals(Object obj) {
94 return obj instanceof Conversation && this.toString().equals(obj.toString());
98 public int hashCode() {
99 return toString().hashCode();
101 // =========================================================================================================
104 public String toString() {
105 return String.format("%s:%d %s:%d", mClientIp, mClientPort, mServerIp, mServerPort);