TDTS06NetworkCourse/lab4/RouterNode.java
2021-08-22 13:22:37 +02:00

207 lines
6.6 KiB
Java

import javax.swing.*;
import java.util.Arrays;
public class RouterNode {
private int myID;
private GuiTextArea myGUI;
private RouterSimulator sim;
private int[] costs = new int[RouterSimulator.NUM_NODES];
private int[] routesCosts = new int[RouterSimulator.NUM_NODES];
private int[] routesList = new int[RouterSimulator.NUM_NODES];
private int[][] distanceTable = new int[RouterSimulator.NUM_NODES][RouterSimulator.NUM_NODES];
// Program parameters
private int CONST_TAB_SIZE = 12; // Constant used to set column width
private boolean POISONED_REVERSE = true; // To set poisoned reverse or not
/* TDTS06 - Lab 4 */
//--------------------------------------------------
// Virtual router constructor, init. base values, distance table, routes table & costs table
public RouterNode(int ID, RouterSimulator sim, int[] costs) {
myID = ID;
this.sim = sim;
myGUI = new GuiTextArea(" Output window for Router #"+ ID + " ");
System.arraycopy(costs, 0, this.costs, 0, RouterSimulator.NUM_NODES);
System.arraycopy(costs, 0, this.routesCosts, 0, RouterSimulator.NUM_NODES);
// Route list initialisation
for (int i = 0; i < sim.NUM_NODES; i++) {
// If the cost is not infinity, we have a route
if (costs[i] != sim.INFINITY){routesList[i] = i;}
else{routesList[i] = -1;}
}
// Distance table initialisation:
// Infinity everywhere...
for (int[] row: distanceTable) {Arrays.fill(row, sim.INFINITY);}
// ...except for itself
distanceTable[myID] = Arrays.copyOf(costs, costs.length);
// Sending first update to neighbour
sendUpdate();
// Printing first distance table
printDistanceTable();
}
//--------------------------------------------------
// Update the route list from the distanceTable
private boolean Update() {
// We are going to check for update to avoid sending useless info.
boolean updt = false;
for (int i = 0; i < sim.NUM_NODES; i++) {
// We ignore ourself
if (i == myID) {continue;}
int newRouteCost = sim.INFINITY;
// We keep the old values in memory
int oldRoute = routesList[i];
int oldRouteCost = distanceTable[myID][i];
for (int j = 0; j < sim.NUM_NODES; j++){
// We keep ignoring ourself
if (j == myID) {continue;}
// If this is a neighbour AND if the new searched route is greater than the actual distance AND if it is not us
if(costs[j] != RouterSimulator.INFINITY && newRouteCost > distanceTable[j][i] + costs[j] && j != myID){
distanceTable[myID][i] = distanceTable[j][i] + costs[j];
newRouteCost = distanceTable[myID][i];
routesList[i] = j;
routesCosts[i] = newRouteCost;
}
}
// If we have changed smth then we have a update
if(oldRoute != routesList[i] || oldRouteCost != distanceTable[myID][i]){
updt = true;
}
}
return updt;
}
//--------------------------------------------------
public void recvUpdate(RouterPacket pkt) {
DEBUG("Rcv packet !");
// Updating the distance table
distanceTable[pkt.sourceid] = pkt.mincost;
// Updating the routes list from the distance table
// and send this update to all neighbour if there
// are changes
if (Update()) {sendUpdate();}
}
//--------------------------------------------------
private void sendUpdate() {
for (int i = 0; i < sim.NUM_NODES; i++) {
int[] sendedCosts = Arrays.copyOf(distanceTable[myID],sim.NUM_NODES);
// We ignore non-neighbor nodes
if(i == myID || costs[i] == sim.INFINITY) {continue;}
// Implementing poisoned reverse
if(POISONED_REVERSE) {
// For all destination nodes, if our route for a other node go thought
// this destination node, we set the distance to infinity to avoid that
// this destination node try to go back thought us and create a loop.
// See page 418 in the course book (4th edition).
for (int j = 0; j < RouterSimulator.NUM_NODES; j++) {
if (routesList[j] == i && j != i) {
sendedCosts[j] = RouterSimulator.INFINITY;
}
}
}
RouterPacket pkt = new RouterPacket(myID,i,sendedCosts);
DEBUG("Sending updt !");
sim.toLayer2(pkt);
}
}
//--------------------------------------------------
// Function that print a table header
private void printTabHeader() {
myGUI.print(F.format("dst",CONST_TAB_SIZE) + " |");
for (int i = 0; i < sim.NUM_NODES ; i++) {myGUI.print(F.format(i,CONST_TAB_SIZE));}
myGUI.println("");
for (int i = 0; i < sim.NUM_NODES ; i++) {
for (int j = 0; j <= 1.5*CONST_TAB_SIZE; j++) {
myGUI.print("-");
}
}
myGUI.println("");
}
//--------------------------------------------------
// Print distance table, costs list & routes list when call
public void printDistanceTable() {
// Header
myGUI.println("Current table for " + myID +
" at time " + sim.getClocktime());
// DistanceTable
myGUI.println("Distancetable: ");
printTabHeader();
// Printing a line for each known routers
for (int i = 0; i < sim.NUM_NODES; ++i ) {
// We ignore non-neighbor nodes
if (costs[i] == sim.INFINITY) continue;
myGUI.print(F.format("nbr " + i, CONST_TAB_SIZE) + "|");
for (int j = 0; j < sim.NUM_NODES; ++j ) {myGUI.print(F.format(distanceTable[i][j],CONST_TAB_SIZE));}
myGUI.println("");
}
myGUI.println("");
// Distance vector & routes
myGUI.println("Our distance vector and routes: ");
printTabHeader();
// Printing costs
myGUI.print(F.format("cost",CONST_TAB_SIZE) + "|");
for (int i = 0; i < sim.NUM_NODES; i++) {
myGUI.print(F.format(routesCosts[i],CONST_TAB_SIZE));
//myGUI.print(F.format(costs[i],CONST_TAB_SIZE));
}
myGUI.println("");
// Printing routes
myGUI.print(F.format("route",CONST_TAB_SIZE) + "|");
for (int i = 0; i < sim.NUM_NODES; i++) {
myGUI.print(F.format(routesList[i],CONST_TAB_SIZE));
}
myGUI.println("");
// Printing info on poisoned reverse
if (POISONED_REVERSE) {
myGUI.println("(Poisoned reverse active)");
}
else {
myGUI.println("(No poisoned reverse)");
}
myGUI.println("\n");
}
//--------------------------------------------------
// If a link change its cost
public void updateLinkCost(int dest, int newcost) {
// Updating costs list
costs[dest] = newcost;
// Spreading the update
if (Update()) {sendUpdate();}
}
// DEBUG FUNCTION - TO REMOVE
private void DEBUG(String str) {
//myGUI.print(" DEBUG from " + myID + " at time " + sim.getClocktime() + ": ");
//myGUI.println(str);
}
}