/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.tools.ldapdecoder.snoop; import java.io.IOException; import java.io.InputStream; /** * This class defines a generic snoop packet record, which holds information * about a packet that has been captured. * * * @author Neil A. Wilson */ public class SnoopPacketRecord { // The actual data associated with this packet record. private byte[] packetData; // The original length of the packet that was captured. private int originalLength; // The total length of this packet record, including the 24-byte header and // any pad bytes that it may have. private int packetRecordLength; // The number of packets dropped by the packet capture software between the // first packet captured and this packet. private int cumulativeDrops; // The time this packet was captured, measured in seconds since January 1, // 1970. private long timestampSeconds; // The number of microseconds after the indicated timestamp in seconds that // the packet was captured. private long timestampMicroseconds; /** * Creates a new snoop packet record with the provided information. * * @param originalLength The original length of the data that was * captured. * @param packetRecordLength The total length of this packet record, * including the header and padding. * @param cumulativeDrops The total number of packets dropped since * the first packet captured. * @param timestampSeconds The time this packet was captured, measured * in seconds since January 1, 1970. * @param timestampMicroseconds The number of microseconds after the * indicated timestamp in seconds that the * packet was captured. * @param packetData The actual data of the packet that was * captured. */ public SnoopPacketRecord(int originalLength, int packetRecordLength, int cumulativeDrops, long timestampSeconds, long timestampMicroseconds, byte[] packetData) { this.originalLength = originalLength; this.packetRecordLength = packetRecordLength; this.cumulativeDrops = cumulativeDrops; this.timestampSeconds = timestampSeconds; this.timestampMicroseconds = timestampMicroseconds; this.packetData = packetData; } /** * Reads a snoop packet record from the provided input stream. * * @param inputStream The input stream from which to read the snoop packet * record. * * @return The snoop packet record that was captured. * * @throws IOException If a problem occurs while reading data from the * provided input stream. * @throws SnoopException If a problem occurs while attempting to decode the * snoop data. */ public static SnoopPacketRecord readPacketRecord(InputStream inputStream) throws IOException, SnoopException { // Read and decode the snoop packet record header. byte[] headerBytes = SnoopDecoder.readBytes(inputStream, 24); if (headerBytes == null) { return null; } int originalLength = SnoopDecoder.byteArrayToInt(headerBytes, 0, 4); int includedLength = SnoopDecoder.byteArrayToInt(headerBytes, 4, 4); int packetRecordLength = SnoopDecoder.byteArrayToInt(headerBytes, 8, 4); int cumulativeDrops = SnoopDecoder.byteArrayToInt(headerBytes, 12, 4); long timestampSeconds = SnoopDecoder.byteArrayToLong(headerBytes, 16, 4); long timestampMicros = SnoopDecoder.byteArrayToLong(headerBytes, 20, 4); // Read the actual packet data. byte[] packetData = SnoopDecoder.readBytes(inputStream, includedLength); if (packetData == null) { throw new SnoopException("End of input stream reached before packet " + "data could be read"); } // Read any pad bytes that might have been included. int numPadBytes = packetRecordLength - includedLength - 24; if (numPadBytes < 0) { throw new SnoopException("Unable to determine number of pad bytes in " + "the snoop packet record"); } else if (numPadBytes > 0) { byte[] padBytes = SnoopDecoder.readBytes(inputStream, numPadBytes); if (padBytes == null) { throw new SnoopException("End of input stream reached before pad " + "bytes could be read"); } } // Create and return the packet record. return new SnoopPacketRecord(originalLength, packetRecordLength, cumulativeDrops, timestampSeconds, timestampMicros, packetData); } /** * Retrieves the number of bytes in the original data packet. * * @return The number of bytes in the original data packet. */ public int getOriginalLength() { return originalLength; } /** * Retrieves the number of bytes actually captured from the data packet. * * @return The number of bytes actually captured from the data packet. */ public int getIncludedLength() { return packetData.length; } /** * Indicates whether this packet is truncated (i.e., the amount of data * captured is less than the amount of data in the original packet). * * @return <CODE>true</CODE> if this packet is truncated, or * <CODE>false</CODE> if not. */ public boolean isTruncated() { return (originalLength != packetData.length); } /** * Retrieves the total number of bytes in this packet record, including the * packet record header and any pad bytes. * * @return The total number of bytes in this packet record. */ public int getPacketRecordLength() { return packetRecordLength; } /** * Retrieves the total number of packets that have been dropped between the * first packet captured and this packet. * * @return The total number of packets that have been dropped between the * first packet captured and this packet. */ public int getCumulativeDrops() { return cumulativeDrops; } /** * Retrieves the time this packet was captured, measured in number of seconds * since January 1, 1970. * * @return The time this packet was captured, measured in number of seconds * since January 1, 1970. */ public long getTimestampSeconds() { return timestampSeconds; } /** * Retrieves the number of microseconds after the specified number of seconds * that this packet was captured. * * @return The number of microseconds after the specified number of seconds * that this packet was captured. */ public long getTimestampMicroseconds() { return timestampMicroseconds; } /** * Retrieves the actual data contained in the packet. * * @return The actual data contained in the packet. */ public byte[] getPacketData() { return packetData; } /** * Retrieves the number of bytes of padding included at the end of this packet * record. * * @return The number of bytes of padding included at the end of this packet * record. */ public int getPadBytes() { return (packetRecordLength - 24 - packetData.length); } }