Package org.jnetpcap.packet

Source Code of org.jnetpcap.packet.JHeader$State

/*
* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Sly Technologies, Inc.
*
* This file is part of jNetPcap.
*
* jNetPcap is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.jnetpcap.packet;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.nio.JStruct;
import org.jnetpcap.packet.format.JFormatter;
import org.jnetpcap.packet.structure.AnnotatedHeader;
import org.jnetpcap.packet.structure.DefaultField;
import org.jnetpcap.packet.structure.JField;
import org.jnetpcap.protocol.JProtocol;

// TODO: Auto-generated Javadoc
/**
* A base class for all protocol header definitions.
*
* @author Mark Bednarczyk
* @author Sly Technologies, Inc.
*/
public abstract class JHeader
    extends
    JBuffer implements JPayloadAccessor {

  /**
   * This class is peered state of a header a native state structure
   *
   * <pre>
   * typedef struct header_t {
   * uint8_t  hdr_id;         // header ID
   *
   * uint8_t  hdr_prefix;     // length of the prefix (preamble) before the header
   * uint8_t  hdr_gap;        // length of the gap between header and payload
   * uint16_t hdr_flags;      // flags for this header
   * uint16_t hdr_postfix;    // length of the postfix (trailer) after the payload
   * uint32_t hdr_offset;     // offset into the packet_t-&gt;data buffer
   * uint32_t hdr_length;     // length of the header in packet_t-&gt;data buffer
   * uint32_t hdr_payload;    // length of the payload
   *
   * jobject  hdr_analysis;   // Java JAnalysis based object if not null
   * } header_t;
   *
   * </pre>
   *
   * .
   *
   * @author Mark Bednarczyk
   * @author Sly Technologies, Inc.
   */
  public static class State
      extends
      JStruct {

    /**
     * Flag set in the header_t structure, tells if the CRC, if performed, was
     * valid or invalid. Invalid CRC means that computed CRC did not match the
     * protocol specific CRC stored within the header.
     */
    public final static int FLAG_CRC_INVALID = 0x0080;

    /**
     * Flag set in the header_t structure, a protocol specific CRC had been
     * performed on the frame, header or its payload.
     */
    public final static int FLAG_CRC_PERFORMED = 0x0040;

    /**
     * Flag set in the header_t structure, which tells if the postifx is
     * incomplete due to packet truncation at the time of the capture.
     */
    public final static int FLAG_GAP_TRUNCATED = 0x0008;

    /**
     * Flag set in the header_t structure, which tells if the header is
     * incomplete due to packet truncation at the time of the capture.
     */
    public final static int FLAG_HEADER_TRUNCATED = 0x0002;

    /**
     * Flag set in the header_t structure, which tells if this header was bound
     * due to a heuristic binding. If set, this means that the header was found
     * heuristically (guessed based on correctness of the field values within
     * the header). It is always possible, that heuristic binding may be
     * incorrect and this flag, provides a way to determine how trust worthy the
     * binding is.
     */
    public final static int FLAG_HEURISTIC_BINDING = 0x0020;

    /**
     * Flag set in the header_t structure, which tells if the payload is
     * incomplete due to packet truncation at the time of the capture. Only
     * protocols with a payload buffer of static length would set this flag or
     * if the payload buffer is at the end of the packet and a calculation can
     * determine based on over-all packet trancation, if the payload was
     * affected as well.
     */
    public final static int FLAG_PAYLOAD_TRUNCATED = 0x0004;

    /**
     * Flag set in the header_t structure, which tells if the postifx is
     * incomplete due to packet truncation at the time of the capture.
     */
    public final static int FLAG_POSTFIX_TRUNCATED = 0x0010;

    /**
     * Flag set in the header_t structure, which tells if the prefix is
     * incomplete due to packet truncation at the time of the capture.
     */
    public final static int FLAG_PREFIX_TRUNCATED = 0x0001;

    /**
     * Flag set in the header_t structure, which indicates that the current
     * header and/or payload are fragmented. The header fragmentation could have
     * been determined by the scanner of this protocol or the flag could have
     * been inherited from encapsulating header.
     */
    public final static int FLAG_HEADER_FRAGMENTED = 0x0100;

    /**
     * Flag set in the header_t structure, which indicates that the current
     * header was dissected for optional fields. All optional fields were
     * recorded.
     */
    public final static int FLAG_FIELDS_DISSECTED = 0x0200;

    /**
     * Flag set in the header_t structure, which indicates that the current
     * header was dissected for optional sub-headers. All optional sub-headers
     * were recorded.
     */
    public final static int FLAG_SUBHEADERS_DISSECTED = 0x0400;

    /**
     * A flag that is set for headers that should not strictly enforce their
     * header boundaries. This is used in cases such as encapsulated IP and ICMP
     * header, where the original IP packet was truncated before encapsulating
     * in ICMP, yet its header tot_length was not adjusted.
     */
    public final static int FLAG_IGNORE_BOUNDS = 0x0800;

    /** Name of the native structure backing this peer class. */
    public final static String STRUCT_NAME = "header_t";

    /**
     * Create an uninitialized type.
     *
     * @param type
     *          type of memory
     */
    public State(Type type) {
      super(STRUCT_NAME, type);
    }

    /**
     * Every header "record" keeps int-bit-flags that describe certain
     * additional information about the header. Most commonly use flags are
     *
     * @return unsigned integer contains bit-flags for this header
     *         {@link #FLAG_PAYLOAD_TRUNCATED} and other like it.
     */
    public native int getFlags();

    /**
     * Gets the length in bytes of a gap (padding) between the header and the
     * protocol 'records' payload:
     *
     * <pre>
     * +------------------=====--------------------+
     * | prefix | header | GAP | payload | postfix |
     * +------------------=====--------------------+
     * </pre>
     *
     * .
     *
     * @return length in bytes of the gap or 0 if not set
     */
    public native int getGap();

    /**
     * Gets the numerical ID of the header this structure describes as defined
     * by <code>JRegistry</code>.
     *
     * @return numerical ID of this header
     * @see JRegistry
     */
    public native int getId();

    /**
     * Gets the length of the protocol's header in bytes within the protocol's
     * 'record':
     *
     * <pre>
     * +---------========--------------------------+
     * | prefix | HEADER | gap | payload | postfix |
     * +---------========--------------------------+
     * </pre>
     *
     * .
     *
     * @return length in bytes of the header
     */
    public native int getLength();

    /**
     * Gets the offset into the packet buffer of the actual protocol header
     * header in bytes of protocols 'record':
     *
     * <pre>
     * +---------========--------------------------+
     * | prefix | HEADER | gap | payload | postfix |
     * +---------========--------------------------+
     * </pre>
     *
     * .
     *
     * @return offset in bytes of the header
     */
    public native int getOffset();

    /**
     * Gets the length of the payload that follows a protocol header in bytes
     * within the protocol's 'record':
     *
     * <pre>
     * +------------------------=========----------+
     * | prefix | header | gap | PAYLOAD | postfix |
     * +------------------------=========----------+
     * </pre>
     *
     * .
     *
     * @return length in bytes of the payload or 0 if not set
     */
    public native int getPayload();

    /**
     * Gets the length of the postfix that follows a protocol's payload in bytes
     * within the protocol's 'record':
     *
     * <pre>
     * +----------------------------------=========+
     * | prefix | header | gap | payload | POSTFIX |
     * +----------------------------------=========+
     * </pre>
     *
     * .
     *
     * @return length in bytes of the postfix or 0 if not set
     */
    public native int getPostfix();

    /**
     * Gets the length of the prefix that precedes a protocol's header in bytes
     * within the protocol's 'record':
     *
     * <pre>
     * +========-----------------------------------+
     * | PREFIX | header | gap | payload | postfix |
     * +========-----------------------------------+
     * </pre>
     *
     * .
     *
     * @return length in bytes of the postfix or 0 if not set
     */
    public native int getPrefix();

    /**
     * Checks if this state object is reading for native structures or has a
     * java implementation backing it.
     *
     * @return true if the implementation is native, otherwise false
     */
    public boolean isDirect() {
      return true;
    }

    /**
     * Peers this state object with the native structures of another. No copies
     * are done, only references are changed.
     *
     * @param peer
     *          destination object holding the native memory reference we need
     *          to peer to
     * @return number of bytes that actually were part of the operation even
     *         though non were physically copied during the peering process
     */
    public int peer(State peer) {
      if (peer.isDirect() == false) {
        throw new IllegalStateException(
            "DirectState can only peer with another DirectState");
      }
      return super.peer(peer);
    }

    /**
     * Sets the header flags to new values.
     *
     * @param flags
     *          unsinged integer containing the bit-flags to set for this header
     */
    public native void setFlags(int flags);

    /**
     * Creates a string containing light debug information about this state
     * class and underlying header it belongs to.
     *
     * @return light debug string for this object and header
     */
    public String toString() {
      return "(id=" + getId() + ", offset=" + getOffset() + ", length="
          + getLength() + ")";
    }
  }

  /**
   * A constant that defines how many bits there are in a byte. This constant is
   * used in unit conversion from bytes to bits and visa-versa. To convert from
   * bytes to bit you multiple your number of bytes by the BYTE constant. To
   * convert from bits to bytes, you divide the number of bits by the BYTE
   * constant.
   */
  public final static int BYTE = 8;

  /** No fields. */
  private final static JField[] DEFAULT_FIELDS = new JField[0];

  /** The Constant EMPTY_HEADER_ARRAY. */
  protected final static JHeader[] EMPTY_HEADER_ARRAY = new JHeader[0];

  /**
   * Gets the size of the native header_t structure on this particular platform.
   *
   * @return length in bytes
   */
  public native static int sizeof();

  /** The annotated header. */
  protected AnnotatedHeader annotatedHeader;

  /** The fields. */
  private JField[] fields;

  /** The id. */
  private int id;

  /** The is sub header. */
  protected boolean isSubHeader = false;

  /** The name. */
  private String name;

  /** The nicname. */
  private String nicname;

  /** A reference to the packet that this header is part of. */
  protected JPacket packet;

  /** Reference to header's native state structure. */
  protected final State state;

  /** The index. */
  private int index = -1;

  /**
   * Calls on the header defintion's static annotated \@HeaderLength method to
   * get header's length. The method is given a buffer and offset as the start
   * of the header. The method invoked must be defined in the header definition
   * otherwise an exception will be thrown.
   */
  public JHeader() {
    super(Type.POINTER);
    order(ByteOrder.BIG_ENDIAN); // network byte order by default
    state = new State(Type.POINTER);

    final JProtocol protocol = JProtocol.valueOf(getClass());

    AnnotatedHeader header;
    if (protocol != null) {
      this.id = protocol.getId();
      header = JRegistry.lookupAnnotatedHeader(protocol);

    } else {
      this.id = JRegistry.lookupId(getClass());
      header = JRegistry.lookupAnnotatedHeader(getClass());
    }

    initFromAnnotatedHeader(header);
  }

  /**
   * Constructs a header and initializes its static fields.
   *
   * @param id
   *          numerical ID of the protocol
   * @param fields
   *          fields usd by the formatter to reformat the packet for output
   * @param name
   *          comprehensive name of the protocol
   */
  public JHeader(int id, JField[] fields, String name) {
    this(id, fields, name, name);
  }

  /**
   * Constructs a header and initializes its static fields.
   *
   * @param id
   *          numerical ID of the protocol
   * @param fields
   *          fields usd by the formatter to reformat the packet for output
   * @param name
   *          comprehensive name of the protocol
   * @param nicname
   *          a short name for the protocol
   */
  public JHeader(int id, JField[] fields, String name, String nicname) {
    super(Type.POINTER);
    this.fields = fields;

    this.id = id;
    this.name = name;
    this.nicname = nicname;
    this.state = new State(Type.POINTER);
    super.order(ByteOrder.nativeOrder());

  }

  /**
   * Constructs a header.
   *
   * @param id
   *          numerical ID of the protocol
   * @param name
   *          comprehensive name of the protocol
   */
  public JHeader(int id, String name) {
    this(id, name, name);
  }

  /**
   * Constructs a header.
   *
   * @param id
   *          numerical ID of the protocol
   * @param name
   *          comprehensive name of the protocol
   * @param nicname
   *          a short name for the protocol
   */
  public JHeader(int id, String name, String nicname) {
    this(id, DEFAULT_FIELDS, name, nicname);
  }

  /**
   * Constructs a header for a CORE protocol.
   *
   * @param protocol
   *          the CORE protocol constant
   */
  public JHeader(JProtocol protocol) {
    super(Type.POINTER);
    order(ByteOrder.BIG_ENDIAN); // network byte order by default
    state = new State(Type.POINTER);

    this.id = protocol.getId();
    AnnotatedHeader header = JRegistry.lookupAnnotatedHeader(protocol);

    initFromAnnotatedHeader(header);
  }

  /**
   * Constructs a header and initializes its static fields.
   *
   * @param state
   *          the default header state object being referenced
   * @param fields
   *          fields usd by the formatter to reformat the packet for output
   * @param name
   *          comprehensive name of the protocol
   * @param nicname
   *          a short name for the protocol
   */
  public JHeader(State state, JField[] fields, String name, String nicname) {
    super(Type.POINTER);

    this.state = state;
    this.fields = fields;
    this.name = name;
    this.nicname = nicname;
    this.id = state.getId();
    super.order(ByteOrder.nativeOrder());
  }



  /**
   * Method that gets called everytime a header is successfully peered with new
   * buffer and/or state structure. This method in JHeader is empty and is
   * expected to be overriden by subclasses of JHeader that require special
   * processing of the header such as decoding its structure at runtime when the
   * header object is bound to new state.
   */
  public final void decode() {
    decodeHeader();
    validateHeader();
  }

  /**
   * Allows a header to decode its complex fields.
   */
  protected void decodeHeader() {
    // Empty
  }

  /**
   * Retrieves the cached annotation of the header definition file. The
   * AT-Header annotation is a class that contains all of the annotation
   * parameters that were set in the definition file or its defaults.
   *
   * @return annotation class for the source header definition
   */
  public AnnotatedHeader getAnnotatedHeader() {
    return this.annotatedHeader;
  }

  /**
   * Retrives the description property for this header as defined in the source
   * definition.
   *
   * @return a short description of this protocol and the header
   */
  public String getDescription() {
    return annotatedHeader.getDescription();
  }

  /**
   * Retrieves the fields at runtime, that this header has so that they may be
   * used by a formatter.
   *
   * @return an array of fields that this header is made up of, as determined at
   *         runtime
   */
  public JField[] getFields() {

    JField.sortFieldByOffset(fields, this, true);

    return this.fields;
  }

  /**
   * Reads the contents of the protocol's 'record' gap property as a byte array.
   *
   * <pre>
   * +------------------=====--------------------+
   * | prefix | header | GAP | payload | postfix |
   * +------------------=====--------------------+
   * </pre>
   *
   * @return contents of the gap or zero length byte[] if not set
   */
  public byte[] getGap() {
    return packet.getByteArray(getGapOffset(), getGapLength());
  }

  /**
   * Reads the length of the gap between the header and payload: *
   *
   * <pre>
   * +------------------=====--------------------+
   * | prefix | header | GAP | payload | postfix |
   * +------------------=====--------------------+
   * </pre>
   *
   * .
   *
   * @return length of the gap in bytes or 0 if not set
   */
  public int getGapLength() {
    return state.getGap();
  }

  /**
   * Gets the offset into the packet, not the header, where the gap starts. Even
   * if the gap is zero length or not set, the offset is still calculated and
   * will always be the first byte past the header.
   *
   * <pre>
   * +------------------=====--------------------+
   * | prefix | header | GAP | payload | postfix |
   * +------------------=====--------------------+
   * </pre>
   *
   * @return offset in bytes into the packet's buffer
   */
  public int getGapOffset() {
    return getOffset() + getHeaderLength();
  }

  /**
   * Convenience method that retrieves the contents of the header as a byte are
   *
   * <pre>
   * +---------========--------------------------+
   * | prefix | HEADER | gap | payload | postfix |
   * +---------========--------------------------+
   * </pre>
   *
   * .
   *
   * @return the contents of the header
   */
  public byte[] getHeader() {
    return packet.getByteArray(getHeaderOffset(), getHeaderLength());
  }

  /**
   * Length of the header in bytes. *
   *
   * <pre>
   * +---------========--------------------------+
   * | prefix | HEADER | gap | payload | postfix |
   * +---------========--------------------------+
   * </pre>
   *
   * @return the length in bytes fo the header
   */
  public int getHeaderLength() {
    return state.getLength();
  }

  /**
   * Gets the offset in bytes into the packet, of the start of the header. *
   *
   * <pre>
   * +---------========--------------------------+
   * | prefix | HEADER | gap | payload | postfix |
   * +---------========--------------------------+
   * </pre>
   *
   * @return offset in bytes into the packet buffer
   */
  public int getHeaderOffset() {
    return state.getOffset();
  }

  /**
   * Gets the numerical ID of this protocol header at runtime as assigned by the
   * JRegistry.
   *
   * @return unique numerical ID of this header
   */
  public final int getId() {
    return this.id;
  }

  /**
   * Length of this header within the buffer.
   *
   * @return length in bytes
   */
  public int getLength() {
    return this.state.getLength();
  }

  /**
   * Gets the comprehensive name for this header.
   *
   * @return the name full name of this header
   */
  public final String getName() {
    return this.name;
  }

  /**
   * Gets the short name for this header.
   *
   * @return the nicname for this header
   */
  public final String getNicname() {
    return this.nicname;
  }

  /**
   * Offset into the packet buffer.
   *
   * @return offset into the buffer in bytes
   */
  public int getOffset() {
    return state.getOffset();
  }

  /**
   * Gets the packet that this header is associated with
   *
   * @return parent packet
   */
  public final JPacket getPacket() {
    return this.packet;
  }

  /**
   * If this is a sub-header of another header, gets the reference to the parent
   * header.
   *
   * @return the parent header if sub-header, otherwise returns a reference to
   *         itself
   */
  public JHeader getParent() {
    return this;
  }

  /**
   * Retrieves the playload data portion of the packet right after the current
   * header.
   *
   * <pre>
   * +------------------------=========----------+
   * | prefix | header | gap | PAYLOAD | postfix |
   * +------------------------=========----------+
   * </pre>
   *
   * @return newly allocated byte array containing copy of the contents of the
   *         header's payload from the packet.
   */
  public byte[] getPayload() {
    return packet.getByteArray(getPayloadOffset(), getPayloadLength());
  }

  /**
   * Gets the length in bytes of the payload that follows the header and the
   * gap. The length reflects the actual data that resides in the captured
   * packet, not neccessarily all of the data that was originaly transmited if
   * the packet has been trucated during capture.
   *
   * <pre>
   * +------------------------=========----------+
   * | prefix | header | gap | PAYLOAD | postfix |
   * +------------------------=========----------+
   * </pre>
   *
   * @return length of the payload in bytes
   */
  public int getPayloadLength() {
    return state.getPayload();
  }

  /**
   * Gets the offset of the payload into the packet buffer.
   *
   * <pre>
   * +------------------------=========----------+
   * | prefix | header | gap | PAYLOAD | postfix |
   * +------------------------=========----------+
   * </pre>
   *
   * @return the start of the payload within the packet buffer
   */
  public int getPayloadOffset() {
    return getGapOffset() + getGapLength();
  }

  /**
   * Gets the contents of the postfix as a byte array.
   *
   * @return the contents of the postfix as a byte array or zero length byte
   *         array if no postfix set
   */
  public byte[] getPostfix() {
    return packet.getByteArray(getPostfixOffset(), getPostfixLength());
  }

  /**
   * Gets the length of the postfix.
   *
   * <pre>
   * +----------------------------------=========+
   * | prefix | header | gap | payload | POSTFIX |
   * +----------------------------------=========+
   * </pre>
   *
   * @return the length of the postfix in bytes or zero if not set
   */
  public int getPostfixLength() {
    return state.getPostfix();
  }

  /**
   * Gets the offset in bytes into the packet buffer of the start of the
   * postfix, even if not set or zero length.
   *
   * @return the offeset into the packet buffer in bytes
   */
  public int getPostfixOffset() {
    return getPayloadOffset() + getPayloadLength();
  }

  /**
   * Gets the contents of the prefix in a byte array.
   *
   * <pre>
   * +========-----------------------------------+
   * | PREFIX | header | gap | payload | postfix |
   * +========-----------------------------------+
   * </pre>
   *
   * @return the contents of the prefix or zero length byte array if not set
   */
  public byte[] getPrefix() {
    return packet.getByteArray(getPrefixOffset(), getPrefixLength());
  }

  /**
   * The length in bytes of the prefix within the packet buffer. Zero if not
   * set.
   *
   * @return the length in bytes within the packet buffer
   */
  public int getPrefixLength() {
    return state.getPrefix();
  }

  /**
   * The offset in bytes into the packet buffer where the prefix starts, even if
   * prefix is not set or zero in length.
   *
   * @return offset in bytes into the packet buffer
   */
  public int getPrefixOffset() {
    return getOffset() - getPrefixLength();
  }

  /**
   * Gets the reference to the current header's native state structure
   *
   * @return current state of the header
   */
  public State getState() {
    return state;
  }

  /**
   * Gets an array of currently defined sub headers.
   *
   * @return array of sub headers
   */
  public JHeader[] getSubHeaders() {
    return EMPTY_HEADER_ARRAY;
  }

  /**
   * Checks if description header property has been set that provides a short
   * description of this header.
   *
   * @return true if header description has been set in Header annotation
   */
  public boolean hasDescription() {
    return annotatedHeader.getDescription() != null;
  }

  /**
   * Checks if gap has been set.
   *
   * @return true if set, otherwise false
   */
  public boolean hasGap() {
    return getGapLength() != 0;
  }

  /**
   * Checks if payload has been set.
   *
   * @return true if set, otherwise false
   */
  public boolean hasPayload() {
    return getPayloadLength() != 0;
  }

  /**
   * Checks if postfix has been set.
   *
   * @return true if set, otherwise false
   */
  public boolean hasPostfix() {
    return getPostfixLength() != 0;
  }

  /**
   * Checks if prefix has been set.
   *
   * @return true if set, otherwise false
   */
  public boolean hasPrefix() {
    return getPrefixLength() != 0;
  }

  /**
   * Checks if header has any sub-headers.
   *
   * @return true if set, otherwise false
   */
  public boolean hasSubHeaders() {
    return false;
  }

  /**
   * Initialize this header directly from annotated header definition class.
   *
   * @param header
   *          annotation to initialize from
   */
  private void initFromAnnotatedHeader(AnnotatedHeader header) {
    this.annotatedHeader = header;

    this.name = header.getName();
    this.nicname = header.getNicname();

    this.fields = DefaultField.fromAnnotatedFields(header.getFields());
  }

  /**
   * Checks if gap has been truncated due to truncation at the time of the
   * capture. If the gap was never set (initially set to zero) and then
   * completely removed because of packet truncation, this method will return
   * false, since the gap never existed in the first place.
   *
   * @return true if truncated, otherwise false
   */
  public boolean isGapTruncated() {
    return (state.getFlags() & State.FLAG_GAP_TRUNCATED) != 0;
  }

  /**
   * Checks if header has been truncated due to truncation at the time of the
   * capture.
   *
   * @return true if truncated, otherwise false
   */
  public boolean isHeaderTruncated() {
    return (state.getFlags() & State.FLAG_HEADER_TRUNCATED) != 0;
  }

  /**
   * Checks if payload has been truncated due to truncation at the time of the
   * capture. If the payload was never set (initially set to zero) and then
   * completely removed because of packet truncation, this method will return
   * false, since the payload never existed in the first place.
   *
   * @return true if truncated, otherwise false
   */
  public boolean isPayloadTruncated() {
    return (state.getFlags() & State.FLAG_PAYLOAD_TRUNCATED) != 0;
  }

  /**
   * Checks if postifx has been truncated due to truncation at the time of the
   * capture. If the postifx was never set (initially set to zero) and then
   * completely removed because of packet truncation, this method will return
   * false, since the postfix never existed in the first place.
   *
   * @return true if truncated, otherwise false
   */
  public boolean isPostfixTruncated() {
    return (state.getFlags() & State.FLAG_POSTFIX_TRUNCATED) != 0;
  }

  /**
   * Checks if prefix has been truncated due to truncation at the time of the
   * capture. If the prefix was never set (initially set to zero) and then
   * completely removed because of packet truncation, this method will return
   * false, since the gap never existed in the first place.
   *
   * @return true if truncated, otherwise false
   */
  public boolean isPrefixTruncated() {
    return (state.getFlags() & State.FLAG_PREFIX_TRUNCATED) != 0;
  }

  /**
   * Peers this state object with the buffer at specified offset.
   *
   * @param buffer
   *          buffer to peer to
   * @param offset
   *          offset into the buffer
   * @return number of bytes that were peered, not copied
   */
  public int peer(JBuffer buffer, int offset) {
    // int length = this.lengthMethod.getHeaderLength(buffer, offset);
    //
    // return peer(buffer, offset, length);

    return 0;
  }

  /**
   * Peers, associates a native packet buffer and scanner structure with this
   * header. This header is unchanged while the header being passed in is
   * rereferenced to point at this headers buffer and state structure.
   *
   * @param header
   *          the header to peer with this header
   * @return number of bytes total that were peered with the supplied header
   */
  public int peer(JHeader header) {
    this.state.peer(header.state);

    return super.peer(header, header.getOffset(), header.getLength());
  }

  /**
   * Peers, without copy, the user supplied buffer with payload data portion of
   * the packet right after the current header.
   *
   * @param buffer
   *          buffer to peer the data with
   * @return the same buffer that was passed in
   */
  public JBuffer peerPayloadTo(JBuffer buffer) {
    final JPacket packet = getPacket();
    final int offset = getOffset() + size();

    buffer.peer(packet, offset, packet.remaining(offset));

    return buffer;
  }

  /**
   * Sets the packet that this header should be associated with
   *
   * @param packet
   *          packet to associate with this header
   */
  public final void setPacket(JPacket packet) {
    this.packet = packet;
  }

  /**
   * Allows sub-headers to be set.
   *
   * @param headers
   *          array of sub header
   */
  public void setSubHeaders(JHeader[] headers) {
  }

  /**
   * Gets a string with summary information about the header.
   *
   * @return String with summary of the header
   */
  public String toString() {
    JFormatter out = JPacket.getFormatter();
    out.reset();
    try {
      out.format(this);
    } catch (IOException e) {
      throw new IllegalStateException("Unexpected StringBuilder IO error");
    }
    return out.toString();
  }

  /**
   * Copies the payload data portion of the packet right after the current
   * header to user supplied buffer.
   *
   * @param buffer
   *          buffer where the data will be written to
   * @return the same buffer that was passed in
   */
  public byte[] transferPayloadTo(byte[] buffer) {
    final JPacket packet = getPacket();
    final int offset = getOffset() + size();

    return packet.getByteArray(offset, buffer);
  }

  /**
   * Copies into the user supplied buffer, the payload data portion of the
   * packet right after the current header. The copy will start at the current
   * ByteBuffer position property.
   *
   * @param buffer
   *          buffer to copy the data to
   * @return the same buffer that was passed in
   */
  public ByteBuffer transferPayloadTo(ByteBuffer buffer) {
    final JPacket packet = getPacket();
    final int offset = getOffset() + size();

    packet.transferTo(buffer, offset, packet.remaining(offset));

    return buffer;
  }

  /**
   * Copies into the user supplied buffer, the payload data portion of the
   * packet right after the current header.
   *
   * @param buffer
   *          buffer to copy the data to
   * @return the same buffer that was passed in
   */
  public JBuffer transferPayloadTo(JBuffer buffer) {
    final JPacket packet = getPacket();
    final int offset = getOffset() + size();

    packet.transferTo(buffer, offset, packet.remaining(offset), 0);

    return buffer;
  }

  /**
   * Sets the index.
   *
   * @param index
   *          the new index
   */
  void setIndex(int index) {
    this.index = index;
  }

  /**
   * Gets the header's index into the packet state structure. Various pieces of
   * information in packet state structure can be looked up using this index.
   *
   * @return header index in Packet.State structure
   */
  public int getIndex() {
    return this.index;
  }

  /**
   * Allows a header to validate its values.
   */
  protected void validateHeader() {

  }

  /**
   * Checks for next header.
   *
   * @return true, if successful
   */
  public boolean hasNextHeader() {
    return this.index + 1 < packet.getState().getHeaderCount();
  }

  /**
   * Gets the next header id.
   *
   * @return the next header id
   */
  public int getNextHeaderId() {
    return packet.getState().getHeaderIdByIndex(index + 1);
  }

  /**
   * Gets the next header offset.
   *
   * @return the next header offset
   */
  public int getNextHeaderOffset() {
    return packet.getState().getHeaderOffsetByIndex(index + 1);
  }

  /**
   * Checks for previous header.
   *
   * @return true, if successful
   */
  public boolean hasPreviousHeader() {
    return this.index > 0;
  }

  /**
   * Gets the previous header id.
   *
   * @return the previous header id
   */
  public int getPreviousHeaderId() {
    return packet.getState().getHeaderIdByIndex(index - 1);
  }

  /**
   * Gets the previous header offset.
   *
   * @return the previous header offset
   */
  public int getPreviousHeaderOffset() {
    return packet.getState().getHeaderOffsetByIndex(index - 1);
  }

  /**
   * Checks if this entire header "record" which includes prefix, header, gap,
   * payload and post is fragmented. The fragmentation may have happened in
   * encapsulating protocol such as Ip. This property may be inherited from
   * encapsulating headers.
   *
   * @return true if this header is believed to be a fragment, otherwise false
   */
  public boolean isFragmented() {
    return ((getState().getFlags() & JHeader.State.FLAG_HEADER_FRAGMENTED) > 0);
  }

}
TOP

Related Classes of org.jnetpcap.packet.JHeader$State

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.