/* * 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 <http://www.gnu.org/licenses/>. */ package com.github.sdnwiselab.sdnwise.application; import com.github.sdnwiselab.sdnwise.adapter.AbstractAdapter; import com.github.sdnwiselab.sdnwise.controller.AbstractController; import com.github.sdnwiselab.sdnwise.controlplane.ControlPlaneLayer; import com.github.sdnwiselab.sdnwise.controlplane.ControlPlaneLogger; import com.github.sdnwiselab.sdnwise.packet.DataPacket; import com.github.sdnwiselab.sdnwise.packet.NetworkPacket; import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.DATA; import com.github.sdnwiselab.sdnwise.topology.NetworkGraph; import com.github.sdnwiselab.sdnwise.util.NodeAddress; import java.util.List; import java.util.Observable; import java.util.concurrent.ArrayBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; /** * Representation of the sensor network and resolver of all the data packets * coming from the network itself. This abstract class has two main private * methods. managePacket and graphUpdate(abstract). The first is called when a * request is coming from the network while the latter is called when something * in the topology of the network changes. * <p> * There are a send and a receive methods to/from the Adaptation Layer * * @author Sebastiano Milardo */ public abstract class AbstractApplication extends ControlPlaneLayer { /** * To avoid garbage collection of the logger. */ protected static final Logger LOGGER = Logger.getLogger("APP"); /** * Incomig packets queue size. */ private static final int QUEUE_SIZE = 1000; /** * Incoming packets queue. */ private final ArrayBlockingQueue<NetworkPacket> bQ; /** * Controller. */ private final AbstractController controller; /** * Creates an Application Abstract Class. * * @param ctrl the controller to be used * @param lower the adapter to be used */ public AbstractApplication(final AbstractController ctrl, final List<AbstractAdapter> lower) { super("APP", lower, null); ControlPlaneLogger.setupLogger(getLayerShortName()); controller = ctrl; bQ = new ArrayBlockingQueue<>(QUEUE_SIZE); } /** * Gets the Network Graph of this AbstractController. * * @return the controller network graph. */ public final NetworkGraph getNetworkGraph() { return controller.getNetworkGraph(); } /** * Invoked every time there is a change in the topology of the network. A * change can be an added/removed node/link or a variation in the rssi * between nodes. The granularity of this updates can be specified in the * NetworkGraph class. */ public abstract void graphUpdate(); /** * Invoked every time a DataPacket is received by the application. * * @param data incoming DataPacket. */ public abstract void receivePacket(final DataPacket data); /** * Sends a generic message to a node. The message is represented by an array * of bytes. * * @param net network id of the dst node * @param dst network address of the dst node * @param message the content of the message to be sent */ public final void sendMessage(final byte net, final NodeAddress dst, final byte[] message) { if (message.length != 0) { DataPacket dp = new DataPacket(net, controller.getSinkAddress(), dst, message); dp.setNxh(controller.getSinkAddress()); getLower().stream().forEach((adapter) -> { adapter.send(dp.toByteArray()); }); } } /** * Sends a generic message to a node. The message is represented by string. * * @param net 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(final byte net, final NodeAddress destination, final String message) { if (message != null && !message.isEmpty()) { sendMessage(net, destination, message.getBytes(UTF8_CHARSET)); } } @Override public final void update(final Observable o, final Object arg) { if (o.equals(getLower())) { try { bQ.put(new NetworkPacket((byte[]) arg)); } catch (InterruptedException ex) { log(Level.SEVERE, ex.toString()); } } } @Override protected final void setupLayer() { new Thread(new Worker()).start(); } /** * Extracts the packets from the incoming queue and send them to the * receivePacket function. */ private class Worker implements Runnable { @Override public void run() { while (true) { try { NetworkPacket data = bQ.take(); if (data.getTyp() == DATA) { receivePacket(new DataPacket(data)); } } catch (InterruptedException ex) { log(Level.SEVERE, ex.toString()); } } } } }