package libcsp.csp.handlers;
import javax.realtime.PeriodicParameters;
import javax.realtime.PriorityParameters;
import javax.safetycritical.PeriodicEventHandler;
import javax.safetycritical.StorageParameters;
import javax.safetycritical.annotate.Level;
import javax.safetycritical.annotate.SCJAllowed;
import libcsp.csp.CSPManager;
import libcsp.csp.ImmortalEntry;
import libcsp.csp.core.ConnectionCore;
import libcsp.csp.core.Node;
import libcsp.csp.core.PacketCore;
import libcsp.csp.core.Port;
import libcsp.csp.transportextentions.ITransportExtension;
import libcsp.csp.transportextentions.TransportUDP;
import libcsp.csp.util.Const;
import libcsp.csp.util.Queue;
public class RouteHandler extends PeriodicEventHandler {
// public static Node[] routeTable;
// public static Port[] portTable;
// public static Queue<PacketCore> packetsToBeProcessed;
private TransportUDP transportExtensionUDP;
public RouteHandler(PriorityParameters priority,
PeriodicParameters parameters, StorageParameters scp,
long scopeSize) {
super(priority, parameters, scp, scopeSize, "[router]");
transportExtensionUDP = new TransportUDP();
}
@Override
@SCJAllowed(Level.SUPPORT)
public void handleAsyncEvent() {
// System.out.println(getName()+" pkts CT " + packetsToBeProcessed.count);
PacketCore packet = ImmortalEntry.packetsToBeProcessed.dequeue(ImmortalEntry.TIMEOUT_SINGLE_ATTEMPT);
if (packet != null) {
byte packetDST = packet.getDST();
System.out.println("[router] packet " + packet.getSRC()
+ "," + packet.getSPORT() + "," + packet.getDST() + ","
+ packet.getDPORT()+":"+packet.data);
// TODO: What if I'm sending a Broadcast packet? The code below wont
// let it to be transmitted. How is a broadcast send with I2C
// anyway.There is a general call address (0x00) to which every
// slave should react
/* The packet is for me */
if (packetDST == CSPManager.nodeAddress || packetDST == ImmortalEntry.ADDRESS_BROADCAST) {
/* Check for an existing connection that should receive the packet */
int connectionIdentifier = ConnectionCore.getConnectionIdFromPacketHeader(packet);
ConnectionCore packetConnection = ImmortalEntry.resourcePool.getGlobalConnection(connectionIdentifier);
/* If its the first packet with no existing connection (server) */
if (packetConnection == null) {
/* Extract the port from the packet header */
Port packetDPORT = ImmortalEntry.portTable[packet.getDPORT()];
if (!packetDPORT.isOpen) {
packetDPORT = ImmortalEntry.portTable[ImmortalEntry.PORT_ANY];
}
/* If a socket listens on the port (server) */
if (packetDPORT.isOpen) {
packetConnection = ImmortalEntry.resourcePool.getConnection(ImmortalEntry.TIMEOUT_SINGLE_ATTEMPT);
if (packetConnection != null) {
/*
* New connection established - Set connection id (reverse src, dst and sport, dport)
* and enqueue connection in the sockets connection queue
*/
try {
packetConnection.setId(packet.getDST(), packet.getDPORT(), packet.getSRC(), packet.getSPORT());
packetConnection.isOpen = true;
packetDPORT.socket.processConnection(packetConnection);
} catch(NullPointerException e) {
packetConnection.dispose();
packetConnection = null;
}
}
}
}
/* Check if we have a connection - then deliver or drop the packet */
if (packetConnection != null) {
ITransportExtension transportExtension = getTransportExtensionForPacket(packet);
transportExtension.deliverPacket(packetConnection, packet);
} else {
packet.dispose();
}
} else { /* The packet is not for me - send it to the destination node through the correct interface */
Node packetDstNode = ImmortalEntry.routeTable[packetDST];
packetDstNode.protocolInterface.transmitPacket(packet);
}
}
}
private ITransportExtension getTransportExtensionForPacket(PacketCore packet) {
/* Inspect header and return the correct transport extension - UDP or RDP */
//TODO: Is this a todo thing?
return transportExtensionUDP;
}
}