2.7.1.1 - How to peer packets

When using JBufferHandler or ByteBufferHandler it may be necessary to peer an actual packet object to the buffers received within the handler. The same restrictions still apply as described in section 2.7.1 about proper usage of libpcap provided ring buffers.

We can easily wrap around the PcapHeader and the buffer received in our handler, with an instance of PcapPacket object. Since we are not going to be doing anything with the packet object outside of our handler, for efficiency we are going to allocate a single private instance of PcapPacket object and mark it final. Here is an example of this usage in JBufferHandler which is the most efficient handler provided by jNetPcap library. The example omits the pcap capture and dispatch loop setup:


JByteBufferHandler<String> handler = new JBufferHandler<String>() {

  private final PcapPacket packet = new PcapPacket(JMemory.POINTER);

  public void nextPacket(PcapHeader header, JBuffer buffer, String msg) {
    packet.peer(buffer); // Peer the data to our packet
    packet.getCaptureHeader().peerTo(header); // Now peer the pcap provided header

    packet.scan(Ethernet.ID); // Assuming that first header in packet is ethernet
  }
}

The handler delivers to us a header and packet data object (both peered to libpcap ring buffer). Both of these objects have a lifecycle only within the handler method and go out of scope outside of it. These objects are not appropriate to put on an outside queue, list or any other storage without copying.

We peer or wrap around libpcap ring buffer memory, with a PcapPacket object. We perform a scan of the headers using the JPacket.scan(int dlt) method. At this point the packet object is suitable to use with protocol headers. We can then use the standard headers like so:

Ip4 ip = new Ip4();
Tcp tcp = new Tcp(); 
if (packet.hasHeader(ip) && packet.hasHeader(tcp)) {
  System.out.println(ip.toString());
  System.out.println(tcp.toString());
}

If we keep our ip and tcp references as handler's fields, all objects we use are only allocated once when the handler is created and reused for every iteration of the packet with no memory copies. This type of handler setup allows the fastest and most efficient processing of captured packets.