1 package edu.uci.iotproject.trafficreassembly.layer2;
3 import org.pcap4j.core.PcapPacket;
4 import org.pcap4j.packet.EthernetPacket;
5 import org.pcap4j.util.MacAddress;
7 import java.util.ArrayList;
8 import java.util.Collections;
12 * Models a layer 2 flow: groups packets exchanged between two specific endpoints (MAC addresses).
14 * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
15 * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
17 public class Layer2Flow {
20 * The first endpoint of this layer 2 flow.
22 private final MacAddress mEndpoint1;
25 * The second endpoint of this layer 2 flow.
27 private final MacAddress mEndpoint2;
30 * Clients observing for changes to this layer 2 flow.
32 private final List<Layer2FlowObserver> mFlowObservers = new ArrayList<>();
34 public Layer2Flow(MacAddress endpoint1, MacAddress endpoint2) {
35 mEndpoint1 = endpoint1;
36 mEndpoint2 = endpoint2;
40 * Get the first endpoint of this flow.
41 * @return the first endpoint of this flow.
43 public MacAddress getEndpoint1() {
48 * Get the second endpoint of this flow.
49 * @return the second endpoint of this flow.
51 public MacAddress getEndpoint2() {
56 * Register as an observer of this flow.
57 * @param observer The client that is to be notified whenever this flow changes (has new packets added).
59 public void addFlowObserver(Layer2FlowObserver observer) {
60 mFlowObservers.add(observer);
64 * Deregister as an observer of this flow.
65 * @param observer The client that no longer wishes to be notified whenever this flow changes.
67 public void removeFlowObserver(Layer2FlowObserver observer) {
68 mFlowObservers.remove(observer);
72 * The packets in the flow.
74 private final List<PcapPacket> mPackets = new ArrayList<>();
77 * Add a packet to this flow.
78 * @param packet The packet that is to be added to the flow.
80 public void addPacket(PcapPacket packet) {
81 verifyAddresses(packet);
83 // Notify flow observers of the new packet
84 mFlowObservers.forEach(o -> o.onNewPacket(this, packet));
88 * Get the packets pertaining to this flow.
89 * @return The packets pertaining to this flow.
91 public List<PcapPacket> getPackets() {
92 return Collections.unmodifiableList(mPackets);
96 * Verify that a packet pertains to this flow.
97 * @param packet The packet that is to be verified.
99 private void verifyAddresses(PcapPacket packet) {
100 EthernetPacket ethPkt = packet.get(EthernetPacket.class);
101 MacAddress srcAddr = ethPkt.getHeader().getSrcAddr();
102 MacAddress dstAddr = ethPkt.getHeader().getDstAddr();
103 if ((mEndpoint1.equals(srcAddr) && mEndpoint2.equals(dstAddr)) ||
104 (mEndpoint1.equals(dstAddr) && mEndpoint2.equals(srcAddr))) {
108 throw new IllegalArgumentException("Mismatch in MACs: packet does not pertain to this flow");
112 public String toString() {
113 return getClass().getSimpleName() + String.format(" with mEndpoint1=%s and mEndpoint2=%s", mEndpoint1, mEndpoint2);