2d804bd16a590ef6bee7ecc66c11cb30ae948674
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / trafficreassembly / layer2 / Layer2Flow.java
1 package edu.uci.iotproject.trafficreassembly.layer2;
2
3 import org.pcap4j.core.PcapPacket;
4 import org.pcap4j.packet.EthernetPacket;
5 import org.pcap4j.util.MacAddress;
6
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.List;
10
11 /**
12  * Models a layer 2 flow: groups packets exchanged between two specific endpoints (MAC addresses).
13  *
14  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
15  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
16  */
17 public class Layer2Flow {
18
19     /**
20      * The first endpoint of this layer 2 flow.
21      */
22     private final MacAddress mEndpoint1;
23
24     /**
25      * The second endpoint of this layer 2 flow.
26      */
27     private final MacAddress mEndpoint2;
28
29     /**
30      * Clients observing for changes to this layer 2 flow.
31      */
32     private final List<Layer2FlowObserver> mFlowObservers = new ArrayList<>();
33
34     public Layer2Flow(MacAddress endpoint1, MacAddress endpoint2) {
35         mEndpoint1 = endpoint1;
36         mEndpoint2 = endpoint2;
37     }
38
39     /**
40      * Register as an observer of this flow.
41      * @param observer The client that is to be notified whenever this flow changes (has new packets added).
42      */
43     public void addFlowObserver(Layer2FlowObserver observer) {
44         mFlowObservers.add(observer);
45     }
46
47     /**
48      * Deregister as an observer of this flow.
49      * @param observer The client that no longer wishes to be notified whenever this flow changes.
50      */
51     public void removeFlowObserver(Layer2FlowObserver observer) {
52         mFlowObservers.remove(observer);
53     }
54
55     /**
56      * The packets in the flow.
57      */
58     private final List<PcapPacket> mPackets = new ArrayList<>();
59
60     /**
61      * Add a packet to this flow.
62      * @param packet The packet that is to be added to the flow.
63      */
64     public void addPacket(PcapPacket packet) {
65         verifyAddresses(packet);
66         mPackets.add(packet);
67         // Notify flow observers of the new packet
68         mFlowObservers.forEach(o -> o.onNewPacket(this, packet));
69     }
70
71     /**
72      * Get the packets pertaining to this flow.
73      * @return The packets pertaining to this flow.
74      */
75     public List<PcapPacket> getPackets() {
76         return Collections.unmodifiableList(mPackets);
77     }
78
79     /**
80      * Verify that a packet pertains to this flow.
81      * @param packet The packet that is to be verified.
82      */
83     private void verifyAddresses(PcapPacket packet) {
84         EthernetPacket ethPkt = packet.get(EthernetPacket.class);
85         MacAddress srcAddr = ethPkt.getHeader().getSrcAddr();
86         MacAddress dstAddr = ethPkt.getHeader().getDstAddr();
87         if ((mEndpoint1.equals(srcAddr) && mEndpoint2.equals(dstAddr)) ||
88                 (mEndpoint1.equals(dstAddr) && mEndpoint2.equals(srcAddr))) {
89             // All is good.
90             return;
91         }
92         throw new IllegalArgumentException("Mismatch in MACs: packet does not pertain to this flow");
93     }
94
95 }