/** * Jeff Rupp * Master's Thesis * 2005 * * base class that any packet used must extend */ package jdr.mobisim; import java.util.*; import org.apache.log4j.*; public abstract class PacketIF { public static final int CRC_SIZE_BYTES = 4; private static Logger m_logger = Logger.getLogger(PacketIF.class); protected static PacketIF s_instance = null; protected static String s_instanceClassName = ""; protected static int s_sequenceNumber = 0; protected static int s_messageNumber = 1; protected double m_hopCount = 0.0; protected static double m_totalHopCount = 0.0; protected double m_powerConsumed = 0.0; protected static double m_totalPowerConsumed = 0.0; protected double m_bitsTransmitted = 0.0; protected static double m_totalBitsTransmitted = 0.0; protected double m_packetTransmitPowerDbm = -1.0; protected static double m_totalPacketCount = 0.0; protected static java.lang.Object m_packetsLock = new java.lang.Object(); /** * The actual data contained in the packet, i.e. what would have been * transmited in the network * contents: * int sourceNode * int destinationNode (-1 == broadcast, all nodes) * int lastNode * int nextNode * byte messageTypeFlags * 0 == inside Cluster message * 1 == between Clusters message * 2 == Cluster establishing message * byte messageLength * byte[messageLength] messageData */ public abstract byte[] getData(); /** * sets the data that would traverse an actual network */ public abstract void setData(byte[] data); /** * get the total number of bits that will be transmitted */ public abstract double getTransmitedBitCount(); /** * The time at which the packet was transmitted */ public abstract long getTransmitTime(); /** * The time at which the packet arrived at its final destination */ public abstract long getArrivalTime(); /** * Sets the arrival time of the packet */ public abstract void setPacketArrived(); /** * increment the number of nodes traversed */ public void IncrementHopCount() { IncrementHopCount(1); } public void IncrementHopCount(int inc) { m_hopCount += inc; synchronized(m_packetsLock) { m_totalHopCount += inc; } } /** * The number of nodes the packet had to pass through on its journey */ public double getHopCount() { return m_hopCount; } public static void ClearPacketHistory() { synchronized(m_packetsLock) { m_totalPacketCount = 0.0; m_totalHopCount = 0.0; m_totalPowerConsumed = 0.0; m_totalBitsTransmitted = 0.0; } } public static double GetAverageNumHops() { double avgHops = 0.0; synchronized(m_packetsLock) { avgHops = m_totalHopCount / m_totalPacketCount; } return avgHops; } public static double GetTotalBitsTransmitted() { return m_totalBitsTransmitted; } /** * the amount of power consumed during this packet's journey */ public double getPowerConsumedInTransit() { return m_powerConsumed; } /** * add to the power consumed for this packet's journey */ public void IncrementPowerConsumedInTransit(double power) { m_powerConsumed += power; synchronized(m_packetsLock) { m_totalPowerConsumed += m_powerConsumed; } } public static double GetAveragePowerConsumed() { double avgPwr = 0.0; synchronized(m_packetsLock) { if(m_totalPacketCount > 0) { avgPwr = (m_totalPowerConsumed / m_totalPacketCount); } } return avgPwr; } public static double GetTotalNumberPackets() { double numPackets = 0; synchronized(m_packetsLock) { numPackets = m_totalPacketCount; } return numPackets; } /** * return a new duplicate packet */ public abstract PacketIF duplicate(); // helper methods to insert and extract different data types public static int extractInt(byte [] data, int offset) { int value = 0; value = (data[offset + 3]) & 0x000000ff; value |= ((data[offset + 2] << 8)) & 0x0000ff00; value |= ((data[offset + 1] << 16)) & 0x00ff0000; value |= ((data[offset + 0] << 24)) & 0xff000000; return value; } public static void insertInt(byte [] data, int offset, int value) { data[offset + 3] = (byte)(value & 0x000000ff); data[offset + 2] = (byte)((value & 0x0000ff00) >> 8); data[offset + 1] = (byte)((value & 0x00ff0000) >> 16); data[offset + 0] = (byte)((value & 0xff000000) >> 24); } /** * get the CRC from the message * simple int sum of all the bytes * @param data the data to CRC, the provided array must be 4 bytes longer than the data * it contains, to allow for the CRC to be added */ public static void AddCrc(byte [] data) { SetCrc(data, GetCrc(data)); } public static int GetCrc(byte [] data) { int crc = 0; // - 4 to allow for the 4 bytes to insert the CRC at the end for(int i = 0; i < (data.length - 4); ++i) { crc += data[i]; } return crc; } public static boolean CheckCrcOk(byte [] data) { int calculatedCrc = GetCrc(data); int storedCrc = extractInt(data, data.length - 4); return (calculatedCrc == storedCrc); } /** * provided to be able to break a packet's CRC */ public static void SetCrc(byte [] data, int newCrc) { insertInt(data, data.length - 4, newCrc); } public static int GetNextSequenceNumber() { return ++s_sequenceNumber; } public static int GetNextMessageNumber() { return ++s_messageNumber; } // dBm = 10 log [Signal (mW)/1mW] public void SetPacketTransmitPowerWatts(double pwrWatts) { SetPacketTransmitPowerDbm(10 * (java.lang.Math.log(pwrWatts*1000)/java.lang.Math.log(10))); } /** * sets the power this packet was transmitted at, used to calculate * the receive power level at a given node */ public void SetPacketTransmitPowerDbm(double pwrDbm) { m_packetTransmitPowerDbm = pwrDbm; } public double GetPacketTransmitPowerDbm() { return m_packetTransmitPowerDbm; } public static PacketIF getInstance() { if((s_instance == null) || (!s_instanceClassName.equals(s_instance.getClass().getName()))) { if(s_instanceClassName.length() > 0) { try { Class inst = Class.forName(s_instanceClassName); s_instance = (PacketIF)inst.newInstance(); } catch(Exception ex) { m_logger.error("Could not create instance of class: "+s_instanceClassName, ex); } } else { m_logger.error("Class name not set"); } } return s_instance; } public static PacketIF getNewInstance() { PacketIF inst = null; if(s_instanceClassName.length() > 0) { try { Class cls = Class.forName(s_instanceClassName); inst = (PacketIF)cls.newInstance(); } catch(Exception ex) { m_logger.error("Could not create instance of class: "+s_instanceClassName, ex); } } else { m_logger.error("Class name not set", new Throwable()); } synchronized(m_packetsLock) { ++m_totalPacketCount; } return inst; } public static void setInstanceClassName(String className) { s_instanceClassName = className; m_logger.debug("PacketIF class name set to: "+ className); } } // end class definition