com.github.sdnwiselab.sdnwise.application.BaseApplication Maven / Gradle / Ivy
/*
* Copyright (C) 2015 SDN-WISE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.github.sdnwiselab.sdnwise.application;
import com.github.sdnwiselab.sdnwise.adapter.Adapter;
import com.github.sdnwiselab.sdnwise.controller.Controller;
import com.github.sdnwiselab.sdnwise.controller.NetworkGraph;
import com.github.sdnwiselab.sdnwise.packet.DataPacket;
import com.github.sdnwiselab.sdnwise.packet.NetworkPacket;
import com.github.sdnwiselab.sdnwise.util.NodeAddress;
import java.util.Observable;
import java.util.Observer;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bouncycastle.util.Strings;
/**
* This class holds a representation of the sensor network and resolves all the
* requests coming from the network itself. This abstract class has two main
* methods. manageRoutingRequest and graphUpdate. The first is called when a
* request is coming from the network while the latter is called when something
* in the tolopogy of the network changes.
*
* There are two main implementation of this class: ControllerDijkstra and
* Controller Static.
*
* This class also offers methods to send messages and configure the nodes in
* the network.
*
* @author Sebastiano Milardo
* @version 0.1
*/
public abstract class BaseApplication implements Observer, Runnable {
final static byte SDN_WISE_DATA = 0;
final static byte SDN_WISE_BEACON = 1;
final static byte SDN_WISE_REPORT = 2;
final static byte SDN_WISE_RESPONSE = 4;
final static byte SDN_WISE_OPEN_PATH = 5;
final static byte SDN_WISE_CONFIG = 6;
private Adapter lower;
final Controller controller;
private final ArrayBlockingQueue bQ;
final Scanner scanner;
public abstract void receivePacket(DataPacket data);
public abstract void graphUpdate();
private boolean isStopped;
public BaseApplication(Controller controller) {
this.controller = controller;
bQ = new ArrayBlockingQueue<>(1000);
scanner = new Scanner(System.in, "UTF-8");
isStopped = false;
}
private void managePacket(NetworkPacket data) {
if (data.getType() == SDN_WISE_DATA){
receivePacket(new DataPacket(data.toByteArray()));
}
}
/**
* This methods manages updates coming from the lower adapter or the network
* representation. When a message is received from the lower adapter it is
* inserted in a ArrayBlockingQueue and then the method managePacket it is
* called on it. While for updates coming from the network representation
* the method graphUpdate is invoked.
*
* @param o
* @param arg
*/
@Override
public final void update(Observable o, Object arg) {
if (o.equals(getLower())) {
try {
bQ.put(new NetworkPacket((byte[]) arg));
} catch (InterruptedException ex) {
Logger.getLogger(BaseApplication.class.getName()).log(
Level.SEVERE, null, ex);
}
}
}
/**
* Starts the working thread that manages incoming requests and it listens
* to messages coming from the standard input.
*/
@Override
public final void run() {
if (getLower().open()) {
Thread th = new Thread(new Worker(bQ));
th.start();
getLower().addObserver(this);
while (!isStopped) {
if (scanner.nextLine().equals("exit -l Controller")) {
isStopped = true;
}
}
}
}
public final void stop(){
isStopped = true;
}
/**
* This method sends a generic message to a node. The message is represented
* by an array of bytes.
*
*
* @param netId network id of the destination node
* @param destination network address of the destination node
* @param message the content of the message to be sent
*/
public final void sendMessage(int netId, NodeAddress destination,
byte[] message) {
byte[] response = new byte[10 + message.length];
response[0] = (byte) response.length;
response[1] = (byte) netId;
response[2] = 0;
response[3] = 0;
response[4] = destination.getHigh();
response[5] = destination.getLow();
response[6] = SDN_WISE_DATA;
response[7] = 20;
response[8] = 0;
response[9] = 0;
System.arraycopy(message, 0, response, 10, message.length);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(BaseApplication.class.getName()).log(Level.SEVERE, null, ex);
}
controller.getLower().send(response);
}
public final void sendMessage(int netId, NodeAddress destination,
String message){
if (message != null && !message.equals("")){
this.sendMessage(netId, destination, Strings.toByteArray(message));
}
}
public final void sendMessage(NetworkPacket packet){
controller.getLower().send(packet.toByteArray());
}
/**
* @param lower the lower to set
*/
public void setLower(Adapter lower) {
this.lower = lower;
}
private class Worker implements Runnable {
private final ArrayBlockingQueue bQ;
boolean isStopped = false;
public Worker(ArrayBlockingQueue bQ) {
this.bQ = bQ;
}
@Override
public void run() {
while (!isStopped) {
try {
managePacket(bQ.take());
} catch (InterruptedException ex) {
isStopped = true;
}
}
}
}
public Adapter getLower() {
return controller.getLower();
}
public NetworkGraph getNetworkGraph(){
return controller.getNetworkGraph();
}
}