The JScanner, JPacket, JHeader, JRegistry and all kind of things came together to make this working jUnit test case not fail and produce output. The test case creates a dummy packet directly in memory, initializes only the Ethernet header with dummy dst and src addresses, but a valid 0x800 type field which specifies that Ip4 is the next header. Ip4 is not initialized therefore all its fields including the hlen field multiplied by 4 will come up with 0 length header. The last header in any packet is always going to be Payload. This is a special type of catch the remainder header that the scanner will always provide.
package org.jnetpcap.packet;
import java.nio.ByteOrder;
import junit.framework.TestCase;
import org.jnetpcap.PcapUtils;
import org.jnetpcap.packet.header.Ethernet;
import org.jnetpcap.packet.header.Ip4;
import org.jnetpcap.packet.header.Ip6;
import org.jnetpcap.packet.header.Payload;
/**
* @author Mark Bednarczyk
* @author Sly Technologies, Inc.
*/
public class TestJScanner
extends TestCase {
public void testScan() {
JPacket packet = new JPacket(64);
packet.setByteArray(0, new byte[] {
(byte) 0xa0,
(byte) 0xa1,
(byte) 0xa2,
(byte) 0xa3,
(byte) 0xa4,
(byte) 0xa5,
(byte) 0xb0,
(byte) 0xb1,
(byte) 0xb2,
(byte) 0xb3,
(byte) 0xb4,
(byte) 0xb5,
(byte) 0x00,
(byte) 0x08, });
JScanner scanner = new JScanner();
scanner.scan(packet, Ethernet.ID);
Ethernet ethernet = new Ethernet();
if (packet.hasHeader(ethernet)) {
System.out.println("Ethernet" + ethernet + " dst="
+ PcapUtils.asString(ethernet.destination())+ " src="
+ PcapUtils.asString(ethernet.source()));
} else {
fail("Didn't find ethernet");
}
Ip4 ip4 = new Ip4();
if (packet.hasHeader(ip4)) {
System.out.println("Ip4" + ip4);
} else {
fail("Didn't find ip4");
}
Payload payload = new Payload();
if (packet.hasHeader(payload)) {
System.out.println("Payload" + payload);
} else {
fail("Didn't find payload");
}
}
}
Which produces this output:
Ethernet(id=1, offset=0, length=14) dst=A0:A1:A2:A3:A4:A5 src=B0:B1:B2:B3:B4:B5 Ip4(id=2, offset=14, length=0) Payload(id=0, offset=14, length=50) scan(): count=3 offset=64 header_map=7
This isn't done yet, but its definitely coming together 
Lastly, for those interested here is what Ethernet header looks like. A header simply extends JHeader class which itself extends JBuffer class which provides all of the getXXX(offset) methods which allow the header to access any part of the header. The constants and almost everything in the header is optional. I haven't added any comments to this yet. The other headers I have so far are just mockups which will be replaced with full blown production quality CORE jNetPcap protocols.
package org.jnetpcap.packet.header;
import java.nio.ByteOrder;
import org.jnetpcap.packet.JHeader;
import org.jnetpcap.packet.JProtocol;
public class Ethernet
extends JHeader {
public static final int ID = JProtocol.ETHERNET_ID;
public static final ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
public static final int LENGTH = 14; // Ethernet header is 14 bytes long
public Ethernet() {
super(ID);
order(BYTE_ORDER);
}
public byte[] destination() {
return getByteArray(0, 6);
}
public byte[] destinationToByteArray(byte[] array) {
return getByteArray(0, array);
}
public void destination(byte[] array) {
setByteArray(0, array);
}
public byte[] source() {
return getByteArray(0 + 6, 6);
}
public void source(byte[] array) {
setByteArray(0 + 6, array);
}
public byte[] sourceToByteArray(byte[] array) {
return getByteArray(0 + 6, array);
}
public int type() {
return getUShort(0 + 12);
}
public void type(int type) {
setUShort(0 + 12, type);
}
The class hierachies are as follows:
JMemory
+->JStruct
| +->JPacket.State // peered with "struct packet_state_t"
| +->JHeader.State // peered with "struct header_t"
| +->JScanner // peered with "struct scanner_t"
|
+-> JBuffer // peered with "unsigned char *"
+->JHeader
| |
| +-> Ethernet
| +-> Ip4
| +-> Ip6
| +-> Tcp
| ...
|
+->JPacket
So JBuffer super class is what is providing all those get/set primitive methods in Ethernet. JBuffer is peered with a packet data buffer, in our case that is the main JPacket buffer that was allocated. So Ethernet and JPacket point to the same native memory, except Ethernet points within that buffer with an offset, which happens to be 0 because its the first header, but Ip4 header for example points to the buffer 14 bytes in and so does Payload since Ip4 header length came out to be 0 becasue of hlen=0 in our dummy packet.
So JPacket and JHeader are peered with the actual data buffer. They each also contains an appropriate State class which holds the state of the packet. This is usually not in the same packet data buffer location, but out of the JScanner allocated memory space, since JScanner is the one producing the packet and header states when it scans. JPacket can be laid out in memory anyway we want, such as contiguously with state header being just in front of the data buffer, JPacket.transferStateAndData method facilitates that copy.