/** * Jeff Rupp * Master's Thesis * 2005 * * The configuration is one protocol per node, thus simulating each node's protocol stack * */ package jdr.mobisim; import java.util.*; import org.apache.log4j.*; import jdr.utils.FloatPoint; public abstract class ProtocolIF { private static final boolean DO_LOADS_OF_LOGS = false; public static final double s_SECONDS_PER_HOUR = 3600.0; private static Logger m_logger = Logger.getLogger(ProtocolIF.class); private static ProtocolIF s_instance = null; private static String s_instanceClassName = ""; public static final int s_BACKOFF = 73; // max simulated clock tics to back off, random max protected static java.util.Random m_backoffRand = new java.util.Random(); protected Vector m_receivedPackets = new Vector(); protected java.lang.Object m_packetQueueLock = new java.lang.Object(); protected int m_myNodeNumber = -1; protected FloatPoint m_location = new FloatPoint(0,0); protected byte m_numberOfHelloTransmitLevels = 3; protected double m_helloTransmitIncrement = MobileNode.MAX_TRANSMIT_POWER_DBM - MobileNode.MIN_TRANSMIT_POWER_DBM; protected double m_wattsConsumed = 0.0; protected static int s_randSeed = 523791; protected static EDU.oswego.cs.dl.util.concurrent.Mutex m_lockSeed = new EDU.oswego.cs.dl.util.concurrent.Mutex(); protected double m_dataRateBps = 100000.0; public ProtocolIF() { } public abstract boolean TransmitData(long xmitTime, int lengthInBits, PacketIF packet, jdr.utils.FloatPoint source, double powerLevel); public abstract boolean TransmitData(long xmitTime, int lengthInBits, PacketIF packet, jdr.utils.FloatPoint source, double powerLevel, boolean doLogs); public abstract boolean AddPacket(PacketIF packet); public abstract void AddNodeHeard(NodeHeard hrd); public abstract void setNodeEventCallbackIf(EventCallbackIF nodeEvtIf); public abstract void Draw(java.awt.Graphics2D graphics, java.awt.Rectangle bounds, double xScale, double yScale); public void setMyNodeNumber(int nodeNum) { m_myNodeNumber = nodeNum; } public void setMyNodeLocation(FloatPoint loc) { m_location = loc; } /** * returns the next packet in the queue, does not remove from queue */ public PacketIF PeekNextPacket() { synchronized(m_packetQueueLock) { if(m_receivedPackets.size() > 0) { return(PacketIF)m_receivedPackets.get(0); } else { return null; } } } /** * returns the next packet in the queue, does remove from queue */ public PacketIF PopNextPacket() { synchronized(m_packetQueueLock) { if(m_receivedPackets.size() > 0) { if(DO_LOADS_OF_LOGS) { m_logger.debug("node: "+m_myNodeNumber + " popped packet from queue"); } return(PacketIF)m_receivedPackets.remove(0); } else { return null; } } } public void SetDataRate(double dataRateBps) { m_dataRateBps = dataRateBps; } public double GetWattsConsumed() { return m_wattsConsumed; } public double IncrementWattsConsumed(double watts) { m_wattsConsumed += watts; return m_wattsConsumed; } public int GetPacketQueueSize() { synchronized(m_packetQueueLock) { return m_receivedPackets.size(); } } public String DumpPacketQueue() { String logStr = ""; int i = 0; PacketIF packet = null; synchronized(m_packetQueueLock) { if(m_receivedPackets.size() > i) { packet = (PacketIF)m_receivedPackets.get(i); ++i; } else { packet = null; } } int numPacketsInQueue = 0; while(packet != null) { byte [] data = packet.getData(); int sourceNode = MobilePacket.extractInt(data, MobilePacket.SOURCE_NODE_BYTE_OFFSET); int destinationNode = MobilePacket.extractInt(data, MobilePacket.DESTINATION_NODE_BYTE_OFFSET); int lastNode = MobilePacket.extractInt(data, MobilePacket.LAST_NODE_BYTE_OFFSET); int nextNode = MobilePacket.extractInt(data, MobilePacket.NEXT_NODE_BYTE_OFFSET); int ackNumber = MobilePacket.extractInt(data, MobilePacket.ACK_SEQUENCE_NUMBER_BYTE_OFFSET); int seqNumber = MobilePacket.extractInt(data, MobilePacket.SEQUENCE_NUMBER_BYTE_OFFSET); byte messageType = data[MobilePacket.MESSAGE_TYPE_BYTE_OFFSET]; byte messageLen = data[MobilePacket.MESSAGE_LENGTH_BYTE_OFFSET]; logStr += "\n source: " + sourceNode+ " msg type: "+ MobilePacket.GetMessageTypeString(messageType); // get the next packet synchronized(m_packetQueueLock) { numPacketsInQueue = m_receivedPackets.size(); if(numPacketsInQueue > i) { packet = (PacketIF)m_receivedPackets.get(i); ++i; } else { packet = null; } } } logStr += "\n total packets in queue: "+numPacketsInQueue; return logStr; } public static int GetNextBackoff() { return (m_backoffRand.nextInt(s_BACKOFF) + 2); // minimum 2 } public void setNumberOfHelloTransmitLevels(byte numLevels) { m_numberOfHelloTransmitLevels = numLevels; if(numLevels > 1) { m_helloTransmitIncrement = (MobileNode.MAX_TRANSMIT_POWER_DBM - MobileNode.MIN_TRANSMIT_POWER_DBM) / (numLevels-1); } else { m_helloTransmitIncrement = MobileNode.MAX_TRANSMIT_POWER_DBM - MobileNode.MIN_TRANSMIT_POWER_DBM; } } public static ProtocolIF 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 = (ProtocolIF)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 ProtocolIF getNewInstance() { ProtocolIF inst = null; if(s_instanceClassName.length() > 0) { try { Class cls = Class.forName(s_instanceClassName); inst = (ProtocolIF)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()); } return inst; } public static void setInstanceClassName(String className) { s_instanceClassName = className; m_logger.debug("ProtocolIF class name set to: "+ className); } }