org.jnetstream.packet
Interface Packet

All Superinterfaces:
java.lang.Iterable<Header>
All Known Subinterfaces:
CapturePacket, DeserializedPacket, FilePacket, LivePacket, NAPPacket, PacketTemplate, PcapPacket, SnoopPacket
All Known Implementing Classes:
TcpNic0Template

public interface Packet
extends java.lang.Iterable<Header>

A packet that has been captured or read from a file and decoded. This is the main interface for accessing packet information and content. The methods getHeader(java.lang.Class) and #getMetaPacket provide access to decoded contents of the packet. The decoding proccess is implementation dependent as to exactly when it happens. The most efficient way is to decode only what is needed to fulfill any given request. Packet content may or may not have been decoded during packet aquisition (reading from file or live capture.) Some packet contents may have been decoded due inorder to evaluate complex filter expressions, or some other such reason. For the most part though the user can assume that no or just minimal decoding of the packet contents has taken place.

Packet decoding is done using the current codec registered for each protocol in the protocol registry. Protocol decoding is done according to the currently set protocol decoding defaults in the protocol registry. The default is to do on-demand protocol decoding which triggers protocol header decoding only when such a header is accessed such as a header interation/traversal or direct call to getHeader.

The headers returned are backed by the packet buffer which contains all of the packet's content. Any changes to the packet's buffer or through the individual header interface must be followed by a call to #update which will cause the previosly returned packet state to be discarded and redecoded. Changes to the packet's or header's buffers can have global consequences within a packet as protocol binding may have been altered or other fields that have dependencies on them. Therefore after each call that modifies the content of the packet buffer you should call update inorder to sychronize the state of the packet structure with the packet buffer. Using and invalidated header due to packet buffer changes may throw IllegalStateException or override some other portion of the packet buffer content.

All operations wheather immutable or mutable are done on the packet buffer. There are numerous ways to modify this packet buffer either directly, through the Packet or PcapBlockHeader API or indirectly outside the current API. All changes should be synchronized after the updates are complete with an update call which will redecode the packet buffer using all the know protocol and NPL definitions.

Lastly, notice that you are able to modify the packet contents that came from a read-only file. This means that although you can modify the packet content, you are not able to flush the changes to a file and you will get an error.

Author:
Mark Bednarczyk, Sly Technologies, Inc.

Nested Class Summary
static class Packet.Property
          Properties which are autogenerated or exported from NPL definition.
 
Method Summary
 void format()
          Formats content of this packet into human readable format using the default formatter and sends the output to the default output device.
 Header[] getAllHeaders()
           
 com.slytechs.utils.memory.BitBuffer getBuffer()
          Gets a buffer that contains the packet's data.
 com.slytechs.utils.memory.BitBuffer getData()
           Returns the undecoded portion of the packet.
<T extends Header>
T
getHeader(java.lang.Class<T> c)
           Returns the specified header from this packet.
<T extends Header>
T
getHeader(Protocol p)
           Same as the alternative version of getHeader(Class) method, but faster.
 int getHeaderCount()
          Returns the number of decoded headers within this packet.
 long getIncludedLength()
          Gets the length of the packet content from the current buffer.
 long getOriginalLength()
          Gets the length of the packet as it was seen on the wire while originally captured.
<A> A
getProperty(Packet.Property property)
           
 long getTimestampNanos()
          Gets the timestamp as recorded at the time of the packet capture in fraction of a second, in nanoseconds.
 long getTimestampSeconds()
          Gets the timestamp as recorded at the time of the packet capture in number of seconds since 1.1.1970.
<T extends Header>
boolean
hasCompleteHeader(java.lang.Class<T> c)
           Checks if a complete, untruncated, header exists in this packet.
<T extends Header>
boolean
hasCompleteHeader(ProtocolInfo<T> p)
           
<T extends Header>
boolean
hasHeader(java.lang.Class<T> c)
           Checks for presence of the specified header within this particular packet.
<T extends Header>
boolean
hasHeader(ProtocolEntry p)
           
 boolean isTruncated()
          Checks if the packet has been truncated from the original length as seen on the network wire.
 java.util.Iterator<Header> iterator()
          Allows all the headers to be iterated through using the foreach() syntax.
 

Method Detail

format

void format()
            throws java.io.IOException
Formats content of this packet into human readable format using the default formatter and sends the output to the default output device.

Throws:
java.io.IOException - any IO errors while sending output

getBuffer

com.slytechs.utils.memory.BitBuffer getBuffer()
                                              throws java.io.IOException
Gets a buffer that contains the packet's data. The the position and limit of the buffer will be set to the start and length of the packet data, respectively. The capacity of the buffer may be more then the limit as the underlying storage or may be allocated larger then actual packet size to preempt possible expansion of the packet data. That is if the buffer the user can exapand the packet by adding fields to it and pushing the "limit" property of the buffer out to as much as buffer's capacity.

Returns:
buffer containing this packet data
Throws:
java.io.IOException

getData

com.slytechs.utils.memory.BitBuffer getData()
                                            throws java.io.IOException

Returns the undecoded portion of the packet. This is typically the data portion of the packet starting at the first octet past the end of the last header decoded in the packet. The buffer returned has its "position", "limit" and "capacity" properties initialized as follows, where position = the start of the undecoded buffer within the main packet buffer. Undecoded buffer position property is set to 0, the limit is set to Packet.getIncludedLength() - position which is the end of the packet data. Capacity is set to Packet.getBuffer().capacity() - position which corresponds to all the underlying packet buffer capacity allocated for this packet. Packets typically captured from a live network interface will not have any extra capacity but packets read from a file or initialized by a user may.

Note that if you modify the contents of this buffer the underlying packet buffer will also be modified and visa versa. Also note that unlike modifying decoded headers it may or may not be neccessary to call update. In the case where you do not want the new packet protocol structure to be redecoded, you do not need to call the #update method. If you append a new header by adding the neccessary byte data into this buffer and you want the new protocol header to be discovered, then you need to call on update method. Afterwards, if all goes well you should be able to call Packet.getLastHeader(MyHeader.class) and get the newly added header. Lastly note that if you do change the structure of the packet and do call update method, you must also call the getUndecodedBuffer method again since the buffer will change due to the new header that was added.

Returns:
a new buffer which contains the undecoded (usually data) portion of the packet
Throws:
java.io.IOException

getHeader

<T extends Header> T getHeader(java.lang.Class<T> c)
                           throws java.lang.IllegalStateException,
                                  java.io.IOException

Returns the specified header from this packet. Before calling this method the hasHeader(java.lang.Class) or hasCompleteHeader(java.lang.Class) calls must be called atleast once for each header being requested. If the check is not made, even though the header exists in the packet, an IllegalStateException will be thrown. This is simlar to standard Iterator's hasNext requirement. The reason for this requirement is that it is the structure of a packet is so dynamic and changing from packet to packet, that this check has been made mandatory and a requirement to prevent unexpected errors. Also note that the same checks have to be done again after a call to #update on a packet. This is because the packet structure may have changed enough that all previously returned headers are no longer valid or exist in the packet. Only the first header of the specified type encountered is returned.

Example:

 for (Packet packet : Captures.openLive(10)) { // Capture 10 packets
        if (packet.hasHeader(Ethernet.class)) {
                Ethernet ethernet = packet.getHeader(Ethernet.class);
                EUI48 destination = ethernet.destination();
                EUI48 source = ethernet.source();
                short type = ethernet.type();
        }
 
        if (packet.hasCompleteHeader(Ip.class)) {
                Ip ip = packet.getHeader(Ip.class);
                // And so forth
        }
 }
 Captures.close(); // Closes last open capture
 

Type Parameters:
T - protocol class type
Parameters:
c - protocol's static class file
Returns:
header of the class type and this method never returns null
Throws:
java.lang.IllegalStateException - thrown if header was not found
java.io.IOException
See Also:
getHeader(Protocol), hasHeader(Class)

getHeader

<T extends Header> T getHeader(Protocol p)
                           throws java.lang.IllegalStateException,
                                  java.io.IOException

Same as the alternative version of getHeader(Class) method, but faster. You can speed up retrieval of headers if you do the lookup of the protocol yourself. The use of parameterized header retrieval ensures compile time type safety of the retrieved header.

Here is an example:

 final Protocol<Ethernet> ETHERNET = ProtocolRegistry.getProtocol(Ethernet.class);
 final Protocol<Ip> IP = ProtocolRegistry.getProtocol(Ip.class);
 
 for (Packet packet: Capture.openLive(10)) {
        if (packet.hasHeader(ETHERNET) {
                Ethernet ethernet = packet.getHeader(ETHERNET);
                // And so forth
        }
 }
 Captures.close(); // Closes last open capture
 

Type Parameters:
T - protocol class type
Parameters:
p - instance of a protocol as retrieved from protocol registry
Returns:
header of the class type and this method never returns null
Throws:
java.lang.IllegalStateException - thrown if header was not found
java.io.IOException
See Also:
getHeader(Class), hasHeader(ProtocolEntry), ProtocolRegistry#getProtocol(Class)

getHeaderCount

int getHeaderCount()
                   throws java.io.IOException
Returns the number of decoded headers within this packet. This method call may encure performance penalty as usually the only way to count how may headers are within packet is to actually iterate and decode parts of each header to the end. This may not neccessarily mean that the headers are decoded completely, but only that portions of the headers is decoded so that the header type of the header following the one being decoded can be assertained.

Returns:
number of currently decoded or decodable headers within the packet
Throws:
java.io.IOException

getIncludedLength

long getIncludedLength()
                       throws java.io.IOException
Gets the length of the packet content from the current buffer. The length is the current length of the available data, which may differ from the original length of the packet if the packet has been trucated. This property can also be accessed using the property object accessor getProperty.

Returns:
length in octets of the full packet size that is contain
Throws:
java.io.IOException

getOriginalLength

long getOriginalLength()
                       throws java.io.IOException
Gets the length of the packet as it was seen on the wire while originally captured. The original length may differ from included length if the captured packet was trucated after the capture and only portion of the packet had been included.

Returns:
length in octets of the full packet size of the original packet as seen on the network wire
Throws:
java.io.IOException

getTimestampNanos

long getTimestampNanos()
                       throws java.io.IOException
Gets the timestamp as recorded at the time of the packet capture in fraction of a second, in nanoseconds. The valid range is from 0 to 999,999,999 nanoseconds. The value is always returned in nanoseconds even when the capturing device, such as a network interface, is not capable of timestamping at nanosecond resolution. In case the capture device has microsecond resolution, the valid value of this counter would be from 0 to 999,999,000. To determine the timestamp real resolution of the capturing device use the method #getCaptureDevice() and then CaptureDevice.getTimestampResolution() which will return an enum constant which describes if the resulution is in nanoseconds or microseconds. In either case this information should only be required in rare circuimstances as the timestamp is always converted and reported in nanoseconds, no matter what the resolution actually is.

Returns:
fraction of a second in nanosecond increments in valid range of 0 to 999,999,999
Throws:
java.io.IOException

getTimestampSeconds

long getTimestampSeconds()
                         throws java.io.IOException
Gets the timestamp as recorded at the time of the packet capture in number of seconds since 1.1.1970.

Returns:
number of seconds
Throws:
java.io.IOException

hasCompleteHeader

<T extends Header> boolean hasCompleteHeader(java.lang.Class<T> c)
                          throws CodecCreateException,
                                 java.io.IOException

Checks if a complete, untruncated, header exists in this packet. If the header exists, but is incomplete due to snaplen, this method will return false. Only the first header of the specified type encountered is returned.

Implementation Note: the check performed is very efficient and does not neccessarily mean that any back-end objects needed to be instantiated. The presence of a header is encoded using bit fields, and checked very efficiently. This method does require a scan of the packet the first time its called, inorder to determine which headers are present, but that is also done very efficiently using low level scanner. Once the single scan of a packet has been performed any subsequent header checks are typically a single bitwise operation.

Type Parameters:
T - Stubfile's header class for the requested header.
Parameters:
c - Class of the header to check for. Java classes for all headers are generated as java stubfiles during NPL definition compile.
Returns:
true if header exists and has not been truncated, false if it exists and has been truncated and also false if it doesn't exist.
Throws:
java.io.IOException
CodecCreateException

hasCompleteHeader

<T extends Header> boolean hasCompleteHeader(ProtocolInfo<T> p)
                          throws CodecCreateException,
                                 java.io.IOException
Throws:
CodecCreateException
java.io.IOException

hasHeader

<T extends Header> boolean hasHeader(java.lang.Class<T> c)
                  throws CodecCreateException,
                         java.io.IOException

Checks for presence of the specified header within this particular packet. The header may be either complete or truncated due to snaplen, but it does exist in this header. Only the first header of the specified type encountered is returned.

Implementation Note: the check performed is very efficient and does not neccessarily mean that any back-end objects needed to be instantiated. The presence of a header is encoded using bit fields, and checked very efficiently. This method does require a scan of the packet the first time its called, inorder to determine which headers are present, but that is also done very efficiently using low level scanner. Once the single scan of a packet has been performed any subsequent header checks are typically a single bitwise operation.

Type Parameters:
T - Stubfile's header class for the requested header.
Parameters:
c - Class of the header to check for. Java classes for all headers are generated as java stubfiles during NPL definition compile.
Returns:
true if header exists
Throws:
java.io.IOException
CodecCreateException

hasHeader

<T extends Header> boolean hasHeader(ProtocolEntry p)
                  throws CodecCreateException,
                         java.io.IOException
Throws:
CodecCreateException
java.io.IOException

isTruncated

boolean isTruncated()
                    throws java.io.IOException
Checks if the packet has been truncated from the original length as seen on the network wire. If snaplen has been set during the packet capture, the data captured is only partial data of the original.

Returns:
true that packet has been truncated, otherwise false
Throws:
java.io.IOException

iterator

java.util.Iterator<Header> iterator()
Allows all the headers to be iterated through using the foreach() syntax.

Specified by:
iterator in interface java.lang.Iterable<Header>
Returns:
iterator that can be used in a foreach() statement. Iterator will iterate through all the headers

getProperty

<A> A getProperty(Packet.Property property)
Parameters:
property -
Returns:

getAllHeaders

Header[] getAllHeaders()
                       throws java.io.IOException
Returns:
Throws:
java.io.IOException