package Ethernet;
import java.util.UUID;
import java.util.HashMap;
import java.lang.Math;
import java.util.Random;
public class Host {
int hostId;
Transmitter tstate;
Receiver rstate;
SimulatedTime stime;
Random r = new Random();
int transAttempt = 0;
int processTime;
int packetSize;
HashMap<UUID, SimulatedEvent> upcomingEvents;
int position; // define this to be the time units from the left-most edge
// of the network
public static double PREAMBLE_TIME = 64.0;
public static double GAP_TIME = 96.0;
public static double JAMMING_TIME = 32.0;
public Host(SimulatedTime parentTime, int pSize, int curPos, int inID)
{
hostId = inID;
tstate = Transmitter.PREPARING;
rstate = Receiver.IDLE;
stime = parentTime;
packetSize = pSize;
position = curPos;
processTime = 10;//Should be random later
}
public void AddFutureEvent(SimulatedEvent simEvt)
{
upcomingEvents.put(simEvt.ID, simEvt);
}
/*
whenever you need to cycle through all events that are in the future
call
while(upcomingEvents.values().Iterator().hasNext())
{
}
*/
public void scheduleMyEvent(SimulatedEvent.SimEvtType type, double startoffset, double dur){
UUID id = UUID.randomUUID();
double currentTime = stime.getCurrentTime();
SimulatedEvent event = new SimulatedEvent(id, type, currentTime + startoffset, dur, this.position);
AddFutureEvent(event);
stime.schedule(event);
}
public void reactToEvent(SimulatedEvent e) {
int currentTime;
UUID id;
int relpos = Math.abs(this.position - e.origin);
switch (rstate) {
case BUSY:
if (e.getEventType() == SimulatedEvent.SimEvtType.JAMMING_DONE ||
e.getEventType() == SimulatedEvent.SimEvtType.TRANS_DONE ) {
if (relpos == 0){
rstate = Receiver.GAP;
scheduleMyEvent(SimulatedEvent.SimEvtType.GAP_DONE, GAP_TIME, 0);
}
scheduleMyEvent(SimulatedEvent.SimEvtType.R_NOW_BUSY,relpos , 0);
rstate = Receiver.GAP;
}
break;
case GAP:
if (e.getEventType() == SimulatedEvent.SimEvtType.GAP_DONE) {
scheduleMyEvent(SimulatedEvent.SimEvtType.R_NOW_IDLE, 0, 0);
rstate = Receiver.IDLE;
}
break;
case IDLE:
if (e.getEventType() == SimulatedEvent.SimEvtType.JAMMING_START ||
e.getEventType() == SimulatedEvent.SimEvtType.PREAMBLE_START ) {
if (relpos == 0){
rstate = Receiver.BUSY;
}
scheduleMyEvent(SimulatedEvent.SimEvtType.R_NOW_BUSY,relpos , 0);
}
break;
}
switch (tstate) {
case EAGER:
if (e.getEventType() == SimulatedEvent.SimEvtType.R_NOW_IDLE ) {
scheduleMyEvent(SimulatedEvent.SimEvtType.PREAMBLE_START, 0, 0);
scheduleMyEvent(SimulatedEvent.SimEvtType.PREAMBLE_DONE, PREAMBLE_TIME, 0);
tstate = Transmitter.PREAMBLE;
}
break;
case PREAMBLE:
if (e.getEventType() == SimulatedEvent.SimEvtType.PREAMBLE_DONE) {
if (rstate == Receiver.IDLE) {
scheduleMyEvent(SimulatedEvent.SimEvtType.SIGNAL_START, 0, 0);
scheduleMyEvent(SimulatedEvent.SimEvtType.SIGNAL_DONE, 0, 0);
tstate = Transmitter.SENDING;
} else {
scheduleMyEvent(SimulatedEvent.SimEvtType.JAMMING_START, 0, 0);
scheduleMyEvent(SimulatedEvent.SimEvtType.JAMMING_DONE, JAMMING_TIME, 0);
tstate = Transmitter.JAMMING;
}
}
break;
case JAMMING:
if (e.getEventType() == SimulatedEvent.SimEvtType.JAMMING_DONE) {
int maxWaitSlots = 1023; // 2 ^ 10 - 1
if(transAttempt < 10)
{
Double power = new Double(Math.pow(2.0, transAttempt));
maxWaitSlots = power.intValue() - 1;
}
if (transAttempt <= 10) {
scheduleMyEvent(SimulatedEvent.SimEvtType.BACKOFF_DONE,((double)r.nextInt(maxWaitSlots)), 0);
} else {
scheduleMyEvent(SimulatedEvent.SimEvtType.BACKOFF_DONE,((double)r.nextInt(maxWaitSlots)), 0);
}
transAttempt++;
tstate = Transmitter.WAITING;
}
break;
case SENDING:
if (e.getEventType() == SimulatedEvent.SimEvtType.R_NOW_BUSY) {
scheduleMyEvent(SimulatedEvent.SimEvtType.JAMMING_START, 0, 0);
scheduleMyEvent(SimulatedEvent.SimEvtType.JAMMING_DONE, JAMMING_TIME, 0);
tstate = Transmitter.JAMMING;
} else if (e.getEventType() == SimulatedEvent.SimEvtType.SIGNAL_DONE) {
scheduleMyEvent(SimulatedEvent.SimEvtType.PACKET_READY, processTime, 0);
tstate = Transmitter.PREPARING;
}
break;
case PREPARING:
if (e.getEventType() == SimulatedEvent.SimEvtType.PACKET_READY) {
if (rstate == Receiver.IDLE) {
scheduleMyEvent(SimulatedEvent.SimEvtType.PREAMBLE_START, 0, 0);
scheduleMyEvent(SimulatedEvent.SimEvtType.PREAMBLE_DONE, PREAMBLE_TIME, 0);
tstate = Transmitter.PREAMBLE;
} else {
tstate = Transmitter.EAGER;
}
}
break;
case WAITING:
if (transAttempt == 15) {
// Packet is Aborted
transAttempt =0;
tstate = Transmitter.PREPARING;
} else if (e.getEventType() == SimulatedEvent.SimEvtType.BACKOFF_DONE) {
if (rstate == Receiver.IDLE) {
scheduleMyEvent(SimulatedEvent.SimEvtType.PREAMBLE_START, 0, 0);
scheduleMyEvent(SimulatedEvent.SimEvtType.PREAMBLE_DONE, PREAMBLE_TIME, 0);
tstate = Transmitter.PREAMBLE;
} else {
tstate = Transmitter.EAGER;
}
}
break;
}
}
public enum Transmitter {
EAGER, PREPARING, PREAMBLE, SENDING, JAMMING, WAITING
}
public enum Receiver {
BUSY, GAP, IDLE
}
}