3.1.2 - Accessing sub-headers in a header

So now that we know how to access any header within a packet, it is time to a peek at the JHeader class. If a complex header has sub-headers, such as optional headers or simply portions of the header that should be treated as a separate sub-header, we can check for their presences and acquire instances to those sub-headers.

We look up sub-headers in the parent header, not the packet. We use a method JHeader.hasSubHeader() does the check for us. The same way we have the convenience method in packet api, we also have a combined hasSubHeader() and getSubHeader() methods in the JHeader class.

A sub-header is a normal header, it actually extends the JHeader baseclass. So once we peer to it, we use it just like any normal header.

Here is an example using ip optional headers:

Ip4 ip = new Ip4();
Ip4.Timestamp ts = new Ip4.Timestamp();
Ip4.LooseSourceRoute lsroute = new Ip4.LooseSourceRoute();
Ip4.StrictSourceRoute ssroute = new Ip4.StrictSourceRoute();

JPacket packet = // We have it from some source

if (packet.hasHeader(ip) && ip.hasSubHeaders()) {

  if (ip.hasSubHeader(lsroute)) {
  }

  if (ip.hasSubHeader(ssroute)) {
  }

  if (ip.hasSubHeader(ts)) {
  }
}

The example leaves the if bodies empty for brevity. Lets take a closer look at what's going on.

Notice that we not only pre-allocate our Ip4 header, but also several optional headers found under Ip4. Those are inner classes but they are static and standalone. Their namespace is tied to Ip4 namespace on purpose. This way you can always expect to find Ip4 optional header under Ip4 namespace. This also prevents name clashes with other sub-headers with the same name but different parent headers.

The example doesn't actually show where we get the packet, it is irrelevant for the purposes of this example. It is important to know that we have a fully decoded packet.

So once the first, outter if statement, checks to see if Ip4 header is present within the packet. If it isn't there is no point in doing any other work (again, a simple single bit check). Within the same condition expression, we also check, but only if the first ip4 part succeeded, if the header has any sub-headers (any at all) set. If there aren't any subheader, we don't need to go into the rest of the logic. If it has any sub-headers set, we enter the outter if statement body. There we individual check with our already peered ip header instance, if it has specific sub-headers.

If a sub-header is found, it is also immediately peered and is ready for us to do whatever the application needs to do.

The important lesson to take from the example, that for sub-headers we are using the JHeader classes API with its hasSubHeader and getSubHeader() calls, not the packets. Those sub-headers theoretically could have their own sub-headers defined as well. You would simply daisy chain the check for the sub-header using sub-headers as parents, and so forth.

if (packet.hasHeader(ip) && ip.hasSubHeader(lsroute) && lsroute.hasSubHeaders()) {
}

Of course, Ip optional header, Loose Source Route, doesn't have any sub-headers, none are defined, therefore the hasSubHeaders() will always return false. We could however have a complex header that has multiple tiers of sub headers.