PcapHandleReader: count and print (to std.err) the number of packets that appear...
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / io / PcapHandleReader.java
1 package edu.uci.iotproject.io;
2
3 import edu.uci.iotproject.analysis.PcapPacketFilter;
4 import org.pcap4j.core.*;
5
6 import java.io.EOFException;
7 import java.util.concurrent.TimeoutException;
8
9 /**
10  * Reads packets from a {@link PcapHandle} (online or offline) and delivers those packets that pass the test exercised
11  * by the provided {@link PcapPacketFilter} onto the provided {@link PacketListener}s.
12  *
13  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
14  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
15  */
16 public class PcapHandleReader {
17
18     private final PcapPacketFilter mPacketFilter;
19     private final PcapHandle mHandle;
20     private final PacketListener[] mPacketListeners;
21
22     /**
23      * Create a {@code PcapHandleReader}.
24      * @param handle An <em>open</em> {@link PcapHandle} that packets will be read from.
25      * @param packetFilter A {@link PcapPacketFilter} that dictates which of the packets read from {@code handle} should
26      *                     be delivered to {@code packetListeners}. Note that while a value of {@code null} is not
27      *                     permitted here, the caller can instead simply provide an implementation that always returns
28      *                     {@code true} if they want to include all packets read from {@code handle}.
29      * @param packetListeners One or more {@link PacketListener}s to which those packets read from {@code handle} that
30      *                        pass through {@code packetFilter} are delivered.
31      */
32     public PcapHandleReader(PcapHandle handle, PcapPacketFilter packetFilter, PacketListener... packetListeners) {
33         mHandle = handle;
34         mPacketFilter = packetFilter;
35         mPacketListeners = packetListeners;
36     }
37
38
39     /**
40      * Start reading (and filtering) packets from the provided {@link PcapHandle}.
41      * @throws PcapNativeException if an error occurs in the pcap native library.
42      * @throws NotOpenException if the provided {@code PcapHandle} is not open.
43      * @throws TimeoutException if packets are being read from a live capture and the timeout expired.
44      */
45     public void readFromHandle() throws PcapNativeException, NotOpenException, TimeoutException {
46         int outOfOrderPackets = 0;
47         try {
48             PcapPacket prevPacket = null;
49             PcapPacket packet;
50             while ((packet = mHandle.getNextPacketEx()) != null) {
51                 if (prevPacket != null && packet.getTimestamp().isBefore(prevPacket.getTimestamp())) {
52                     outOfOrderPackets++;
53                     /*
54                     // Fail early if assumption doesn't hold.
55                     mHandle.close();
56                     throw new AssertionError("Packets not in ascending temporal order");
57                     */
58                 }
59                 if (mPacketFilter.shouldIncludePacket(packet)) {
60                     // Packet accepted for inclusion; deliver it to observing client code.
61                     for (PacketListener consumer : mPacketListeners) {
62                         consumer.gotPacket(packet);
63                     }
64                 }
65                 prevPacket = packet;
66             }
67         } catch (EOFException eof) {
68             // Reached end of file. All good.
69             System.out.println(String.format("%s: finished reading pcap file", getClass().getSimpleName()));
70         }
71         if (outOfOrderPackets > 0) {
72             System.err.println(
73                     String.format("[[[ %s: %d packets appeared out of order (with regards to their timestamps) ]]]",
74                             getClass().getSimpleName(), outOfOrderPackets));
75         }
76         mHandle.close();
77     }
78
79 }