Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.sdnwiselab.sdnwise.node.Node 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.node;
import com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction.SDN_WISE_AGGREGATE;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction.SDN_WISE_DROP;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction.SDN_WISE_FORWARD_BROADCAST;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction.SDN_WISE_FORWARD_UNICAST;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction.SDN_WISE_FORWARD_UP;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableAction.SDN_WISE_MODIFY;
import com.github.sdnwiselab.sdnwise.flowtable.FlowTableEntry;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableEntry.SDN_WISE_WINDOWS_MAX;
import com.github.sdnwiselab.sdnwise.flowtable.FlowTableStats;
import com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_BIGGER;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_EQUAL;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_EQUAL_OR_BIGGER;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_EQUAL_OR_LESS;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_LESS;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_NOT_EQUAL;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_PACKET;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_SIZE_0;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_SIZE_1;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableWindow.SDN_WISE_SIZE_2;
import com.github.sdnwiselab.sdnwise.function.FunctionInterface;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_ACCEPTED_ID_MAX;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_BEACON_HDR_LEN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_DFLT_CNT_BEACON_MAX;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_DFLT_CNT_REPORT_MAX;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_DFLT_CNT_UPDTABLE_MAX;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_DFLT_HDR_LEN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_DFLT_RSSI_MIN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_MAC_SEND_BROADCAST;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_MAC_SEND_UNICAST;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_NEIGHBORS_MAX;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_OPEN_PATH_HDR_LEN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_REPORT_HDR_LEN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_RESPONSE_HDR_LEN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_RLS_MAX;
import static com.github.sdnwiselab.sdnwise.flowtable.FlowTableEntry.SDN_WISE_RULE_COPY_LEN;
import static com.github.sdnwiselab.sdnwise.node.Constants.SDN_WISE_RL_TTL_DECR;
import com.github.sdnwiselab.sdnwise.packet.NetworkPacket;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_BATT;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_BEACON;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_CONFIG;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_DATA;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_DFLT_TTL_MAX;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_DIST;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_DST_H;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_DST_L;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_LEN;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_NEIGH;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_NET_ID;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_NXHOP_H;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_NXHOP_L;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_OPEN_PATH;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_REPORT;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_RESPONSE;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_SRC_H;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_SRC_L;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_TTL;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.SDN_WISE_TYPE;
import com.github.sdnwiselab.sdnwise.util.Neighbor;
import com.github.sdnwiselab.sdnwise.util.NodeAddress;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
/**
*
* @author Sebastiano Milardo
*/
public abstract class Node implements Runnable {
private static final String digits = "0123456789abcdef";
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Thread th;
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
if (Security.getProvider("BC") == null) {
System.out.println("Provider(\"BC\") not installed");
} else {
System.out.println("Provider(\"BC\") installed");
}
if (args.length == 7) {
if (args[0].equals("SINK")) {
th = new Thread(new SinkNode(
// its own id
(byte) Integer.parseInt(args[1]),
// its own address
new NodeAddress(args[2]),
// listener port
Integer.parseInt(args[3]),
// controller address
args[4],
// controller port
Integer.parseInt(args[5]),
// neigh file
args[6],
// security
false)
);
th.start();
}
} else if (args.length == 5) {
if (args[0].equals("NODE")) {
th = new Thread(new SensorNode(
// its own id
(byte) Integer.parseInt(args[1]),
// its own address
new NodeAddress(args[2]),
// listener port
Integer.parseInt(args[3]),
// neigh file
args[4], false)
);
th.start();
}
}
}
/**
* Return length many bytes of the passed in byte array as a hex string.
*
* @param data the bytes to be converted.
* @param length the number of bytes in the data block to be converted.
* @return a hex representation of length bytes of data.
*/
public static String toHex(byte[] data, int length) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buf.append(digits.charAt(v >> 4));
buf.append(digits.charAt(v & 0xf));
}
return buf.toString();
}
/**
* Return the passed in byte array as a hex string.
*
* @param data the bytes to be converted.
* @return a hex representation of data.
*/
public static String toHex(byte[] data) {
return toHex(data, data.length);
}
int port;
DatagramSocket socket;
final ArrayBlockingQueue messageQueue;
HashMap neighbourList;
String configNeighbourFilePath;
private int num_hop_vs_sink;
private int rssi_vs_sink;
Battery battery;
int semaphore,
flow_table_free_pos,
accepted_id_free_pos,
neighbors_number;
private final byte[] buf;
ArrayList neighborTable;
ArrayList flowTable;
ArrayList acceptedId;
int[] statusRegister;
HashMap adcRegister;
HashMap> functionBuffer = new HashMap<>();
HashMap functions = new HashMap<>();
NodeAddress addr;
int net_id;
int cnt_beacon_max;
int cnt_report_max;
int cnt_updtable_max;
int cnt_sleep_max;
int ttl_max;
int rssi_min;
boolean isSecure = false;
Cipher cipher;
KeyPair pair;
Key pubKey, privKey;
PublicKey sinkPubKey;
public Node(NodeAddress addr, byte net_id, int port, String configNeighbourFilePath, boolean isSecure) {
buf = new byte[1024];
statusRegister = new int[1024];
neighborTable = new ArrayList<>(SDN_WISE_NEIGHBORS_MAX);
acceptedId = new ArrayList<>(SDN_WISE_ACCEPTED_ID_MAX);
flowTable = new ArrayList<>(SDN_WISE_RLS_MAX);
messageQueue = new ArrayBlockingQueue<>(1024);
this.addr = addr;
this.net_id = net_id;
this.configNeighbourFilePath = configNeighbourFilePath;
neighbourList = new HashMap<>();
this.port = port;
this.isSecure = isSecure;
setup();
}
public void setNum_hop_vs_sink(int num_hop_vs_sink) {
this.num_hop_vs_sink = num_hop_vs_sink;
}
public void setRssi_vs_sink(int rssi_vs_sink) {
this.rssi_vs_sink = rssi_vs_sink;
}
public void setSemaphore(int semaforo) {
this.semaphore = semaforo;
}
public int getNum_hop_vs_sink() {
return num_hop_vs_sink;
}
public int getRssi_vs_sink() {
return rssi_vs_sink;
}
public int getSemaphore() {
return semaphore;
}
private void setup() {
initSdnWise();
initFlowTable();
initNeighborTable();
initAcceptedId();
//boolean
if (isSecure == true) {
setupSecurity();
}
}
public abstract void setupSecurity();
// questi due metodi sono inglobati nel tx e rx Beacon
public int[] sendPublicKey(int[] packet) {
int[] newPacket = new int[packet.length + sinkPubKey.getEncoded().length];
System.arraycopy(packet, 0, newPacket, 0, packet.length);
arraycopy(sinkPubKey.getEncoded(), 0, newPacket, packet.length, sinkPubKey.getEncoded().length);
newPacket[SDN_WISE_LEN] = newPacket.length;
return newPacket;
}
public void receivePublicKey(int[] allPacket, int keyLen) {
byte[] sinkPubKeyArray = new byte[keyLen]; // lo sappiamo quanto di e'
arraycopy(allPacket, allPacket.length - sinkPubKeyArray.length,
sinkPubKeyArray, 0, sinkPubKeyArray.length);
try {
sinkPubKey = KeyFactory.getInstance("RSA").
generatePublic(new X509EncodedKeySpec(sinkPubKeyArray));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeySpecException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
}
//
public int[] sendSignedMessage(int[] packet) {
if (packet.length > SDN_WISE_DFLT_HDR_LEN) {
byte[] plainPacket = new byte[packet.length - SDN_WISE_DFLT_HDR_LEN];
try {
arraycopy(packet, SDN_WISE_DFLT_HDR_LEN,
plainPacket, 0, packet.length - SDN_WISE_DFLT_HDR_LEN);
MessageDigest messageHash = MessageDigest.getInstance("SHA1", "BC");
byte[] messageHashed = messageHash.digest(plainPacket);
System.out.println("plainMessage: " + Arrays.toString(plainPacket));
System.out.println("plainMessageString: " + toHex(plainPacket));
System.out.println("messageHashed : " + Arrays.toString(messageHashed));
System.out.println("messageHashedString : " + toHex(messageHashed));
System.out.println("messageHashed Length: " + messageHashed.length);
System.out.println("messageHashedString Length: " + (toHex(messageHashed)).length());
cipher.init(Cipher.ENCRYPT_MODE, privKey);// ,random
byte[] encryptedPart = cipher.doFinal(messageHashed);
System.out.println("cipher: " + toHex(encryptedPart));
System.out.println("cipher lenght: " + toHex(encryptedPart).length());
System.out.println("cipher[] : " + Arrays.toString(encryptedPart));
System.out.println("cipher[] lenght: " + encryptedPart.length);
System.out.println("Encrypted Hashed Message Sent!");
int[] newPacket = new int[packet.length + encryptedPart.length];
System.arraycopy(packet, 0, newPacket, 0, packet.length);
arraycopy(encryptedPart, 0, newPacket, packet.length, encryptedPart.length);
return newPacket;
} catch (NoSuchAlgorithmException |
NoSuchProviderException |
InvalidKeyException |
IllegalBlockSizeException |
BadPaddingException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
}
return packet;
}
public int[] receiveSignedMessage(int[] allPacket) {
byte[] encryptedPart = new byte[22];
byte[] plainPart = new byte[allPacket.length - encryptedPart.length - SDN_WISE_DFLT_HDR_LEN];
arraycopy(allPacket, SDN_WISE_DFLT_HDR_LEN, plainPart, 0, plainPart.length);
arraycopy(allPacket, allPacket.length - encryptedPart.length,
encryptedPart, 0, encryptedPart.length);
try {
// decryption step
//Cipher cipher = Cipher.getInstance("RSA/None/NoPadding", "BC");
cipher.init(Cipher.DECRYPT_MODE, sinkPubKey);
byte[] hashedPart = cipher.doFinal(encryptedPart);
MessageDigest hashedPlainPart = MessageDigest.getInstance("SHA1", "BC");
byte[] hastToVerify = hashedPlainPart.digest(plainPart);
//verifica autenticita' messaggio
if (Arrays.equals(hashedPart, hastToVerify)) {
System.out.println("Signature Verification Correct");
return allPacket;
} else {
System.out.println("Signature Verification Failed");
return null;
}
} catch (InvalidKeyException |
IllegalBlockSizeException |
BadPaddingException |
NoSuchAlgorithmException |
NoSuchProviderException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public void initSdnWise() {
cnt_beacon_max = SDN_WISE_DFLT_CNT_BEACON_MAX;
cnt_report_max = SDN_WISE_DFLT_CNT_REPORT_MAX;
cnt_updtable_max = SDN_WISE_DFLT_CNT_UPDTABLE_MAX;
rssi_min = SDN_WISE_DFLT_RSSI_MIN;
ttl_max = SDN_WISE_DFLT_TTL_MAX;
battery = new Battery();
flow_table_free_pos = 1;
accepted_id_free_pos = 0;
InputStream is = this.getClass().getResourceAsStream("/"+configNeighbourFilePath);
try (BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"))) {
String line;
while ((line = br.readLine()) != null) {
String[] tmp = line.split(",");
if (tmp.length == 4) {
neighbourList.put(new NodeAddress(tmp[0]), new FakeInfo(
new InetSocketAddress(tmp[1],
Integer.parseInt(tmp[2])),
Integer.parseInt(tmp[3]))
);
}
}
} catch (Exception ex) {
Logger.getLogger(SinkNode.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void initFlowTable() {
for (int i = 0; i < SDN_WISE_RLS_MAX; i++) {
flowTable.add(i, new FlowTableEntry());
}
int i, k;
flowTable.get(0).getWindow()[0]
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLocation(SDN_WISE_PACKET)
.setPos(SDN_WISE_DST_H)
.setValueHigh(0)
.setValueLow(0);
flowTable.get(0).getWindow()[1]
.setOperator(SDN_WISE_NOT_EQUAL)
.setSize(SDN_WISE_SIZE_1)
.setLocation(SDN_WISE_PACKET)
.setPos(SDN_WISE_TYPE)
.setValueHigh(0)
.setValueLow(0);
for (k = 2; k < SDN_WISE_WINDOWS_MAX; k++) {
flowTable.get(0).getWindow()[k] = new FlowTableWindow();
}
flowTable.get(0).getAction()
.setType(SDN_WISE_FORWARD_UNICAST)
.setLocation(SDN_WISE_PACKET)
.setPos(SDN_WISE_NXHOP_H)
.setValueHigh(0)
.setValueLow(0);
flowTable.get(0).setStats(new FlowTableStats());
for (i = 1; i < SDN_WISE_RLS_MAX; i++) {
initRule(flowTable.get(i));
}
}
public void initNeighborTable() {
int i;
for (i = 0; i < SDN_WISE_NEIGHBORS_MAX; i++) {
neighborTable.add(i, new Neighbor());
}
neighbors_number = 0;
}
public void initAcceptedId() {
int i;
for (i = 0; i < SDN_WISE_ACCEPTED_ID_MAX; i++) {
acceptedId.add(i, new NodeAddress(65535));
}
}
public void initRule(FlowTableEntry rule) {
int i;
for (i = 0; i < SDN_WISE_WINDOWS_MAX; i++) {
rule.getWindow()[i] = new FlowTableWindow();
}
rule.setAction(new FlowTableAction());
rule.setStats(new FlowTableStats());
}
public int chooseNeighbor(int action_value_2_byte) {
int i;
for (i = 0; i < SDN_WISE_NEIGHBORS_MAX; i++) {
if (action_value_2_byte == neighborTable.get(i).getAddr().getLow()) {
return (neighborTable.get(i).getAddr().getHigh());
}
}
return 254;
}
public void resetSemaphore() {
}
@Override
public void run() {
try {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket = new DatagramSocket(port);
new Timer().schedule(new Task(), 1000, 1000);
new Thread(new PacketManager()).start();
while (true) {
socket.receive(packet);
int[] tmp = new int[packet.getData()[0]];
for (int i = 0; i < packet.getLength(); i++) {
tmp[i] = packet.getData()[i] & 0xFF;
}
messageQueue.put(tmp);
}
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
}
void txBEACON() {
int[] packet = new int[SDN_WISE_BEACON_HDR_LEN];
packet[SDN_WISE_LEN] = SDN_WISE_BEACON_HDR_LEN;
packet[SDN_WISE_NET_ID] = net_id;
packet[SDN_WISE_SRC_H] = addr.getHigh();
packet[SDN_WISE_SRC_L] = addr.getLow();
packet[SDN_WISE_DST_H] = 255; // Broadcast
packet[SDN_WISE_DST_L] = 255;
packet[SDN_WISE_TYPE] = SDN_WISE_BEACON;
packet[SDN_WISE_TTL] = ttl_max;
packet[SDN_WISE_DIST] = num_hop_vs_sink;
packet[SDN_WISE_BATT] = battery.getBatteryPercent();
if (num_hop_vs_sink == 0) {
packet[SDN_WISE_NXHOP_H] = addr.getHigh();
packet[SDN_WISE_NXHOP_L] = addr.getLow();
} else {
packet[SDN_WISE_NXHOP_H] = flowTable.get(0).getWindow()[0].getValueHigh();
packet[SDN_WISE_NXHOP_L] = flowTable.get(0).getWindow()[0].getValueLow();
}
if (this.isSecure) {
packet = sendPublicKey(packet);
}
radioTX(packet, SDN_WISE_MAC_SEND_BROADCAST);
}
void txREPORT() {
int i = 0;
int[] packet = new int[16 + SDN_WISE_NEIGHBORS_MAX * 3];
packet[SDN_WISE_NET_ID] = net_id;
packet[SDN_WISE_SRC_H] = addr.getHigh();
packet[SDN_WISE_SRC_L] = addr.getLow();
packet[SDN_WISE_DST_H] = flowTable.get(0).getWindow()[0].getValueHigh(); // indirizzo del sink
packet[SDN_WISE_DST_L] = flowTable.get(0).getWindow()[0].getValueLow();;
packet[SDN_WISE_TYPE] = SDN_WISE_REPORT;
packet[SDN_WISE_TTL] = ttl_max;
packet[SDN_WISE_NXHOP_H] = flowTable.get(0).getAction().getValueHigh();
// Nel seguito si farà uso dell'accesso diretto a qst
packet[SDN_WISE_NXHOP_L] = flowTable.get(0).getAction().getValueLow();
// ints perchè la regola 0 è sempre diretta verso il sink
packet[SDN_WISE_DIST] = num_hop_vs_sink;
packet[SDN_WISE_BATT] = battery.getBatteryPercent();
packet[SDN_WISE_NEIGH] = neighbors_number; //numero di vicini
packet[SDN_WISE_LEN] = ((neighbors_number * 3) + SDN_WISE_REPORT_HDR_LEN);
for (int j = 0; j < packet[SDN_WISE_NEIGH]; j++) {
//Vicino i
packet[SDN_WISE_REPORT_HDR_LEN + i] = neighborTable.get(j)
.getAddr().getHigh();
i++;
packet[SDN_WISE_REPORT_HDR_LEN + i] = neighborTable.get(j)
.getAddr().getLow();
i++;
//RSSI vs Vicino
packet[SDN_WISE_REPORT_HDR_LEN + i] = neighborTable.get(j)
.getRssi();
i++;
}
initNeighborTable();
controllerTX(Arrays.copyOf(packet, packet[SDN_WISE_LEN]));
}
void updateTable() {
for (int i = 0; i < SDN_WISE_RLS_MAX; i++) {
int ttl = flowTable.get(i).getStats().getTtl();
if (ttl >= SDN_WISE_RL_TTL_DECR) {
flowTable.get(i).getStats().setTtl((ttl - SDN_WISE_RL_TTL_DECR));
} else {
initRule(flowTable.get(i));
if (i == 0) {
resetSemaphore();
}
}
}
}
void rxDATA(int[] packet) {
if (isAcceptedIdPacket(packet)) {
SDN_WISE_Callback(packet);
} else if (isAcceptedIdAddress(
packet[SDN_WISE_NXHOP_H],
packet[SDN_WISE_NXHOP_L])) {
runFlowMatch(packet);
}
}
void rxBEACON(int[] packet, int rssi) {
int index = getNeighborIndex(new NodeAddress(packet[SDN_WISE_SRC_H],
packet[SDN_WISE_SRC_L]));
if (index != (SDN_WISE_NEIGHBORS_MAX + 1)) {
if (index != -1) {
neighborTable.get(index).setRssi(rssi);
neighborTable.get(index).setBatt(packet[SDN_WISE_BATT]);
} else {
neighborTable.get(neighbors_number).setAddr(
new NodeAddress(packet[SDN_WISE_SRC_H],
packet[SDN_WISE_SRC_L]));
neighborTable.get(neighbors_number).setRssi(rssi);
neighborTable.get(neighbors_number).setBatt(packet[SDN_WISE_BATT]);
neighbors_number++;
}
}
}
abstract void rxREPORT(int[] packet);
void rxRESPONSE(int[] packet) {
if (isAcceptedIdPacket(packet)) {
// Si memorizza la regola nella tabella
// Vedo se esiste una regola uguale
// Vedo quante regole ci sono nel pacchetto
int nRules = (packet[SDN_WISE_LEN] - SDN_WISE_RESPONSE_HDR_LEN) / SDN_WISE_RULE_COPY_LEN;
if ((nRules * SDN_WISE_RULE_COPY_LEN) + SDN_WISE_RESPONSE_HDR_LEN == packet[SDN_WISE_LEN]) {
for (int i = 0; i < nRules; i++) {
FlowTableEntry rule = new FlowTableEntry();
int j;
int packet_index = SDN_WISE_RESPONSE_HDR_LEN;
for (j = 0; j < SDN_WISE_WINDOWS_MAX; j++) {
rule.getWindow()[j].setOp(packet[packet_index]);
packet_index++;
rule.getWindow()[j].setPos(packet[packet_index]);
packet_index++;
rule.getWindow()[j].setValueHigh(packet[packet_index]);
packet_index++;
rule.getWindow()[j].setValueLow(packet[packet_index]);
packet_index++;
}
rule.getAction().setAct(packet[packet_index]);
packet_index++;
rule.getAction().setPos(packet[packet_index]);
packet_index++;
rule.getAction().setValueHigh(packet[packet_index]);
packet_index++;
rule.getAction().setValueLow(packet[packet_index]);
packet_index++;
rule.setStats(new FlowTableStats());
insertRule(rule, searchRule(rule));
}
}
} else {
runFlowMatch(packet);
}
}
void rxOPEN_PATH(int[] packet) {
if (isAcceptedIdPacket(packet)) {
int i;
i = SDN_WISE_OPEN_PATH_HDR_LEN;
NodeAddress last_path_addr
= new NodeAddress(packet[packet[SDN_WISE_LEN] - 2],
packet[packet[SDN_WISE_LEN] - 1]);
NodeAddress first_path_addr
= new NodeAddress(packet[SDN_WISE_OPEN_PATH_HDR_LEN],
packet[SDN_WISE_OPEN_PATH_HDR_LEN + 1]);
// mi cerco
while (i < packet[SDN_WISE_LEN]) {
// mi trovo
if (isAcceptedIdAddress(packet[i], packet[i + 1])) {
NodeAddress actual_address
= new NodeAddress(packet[i], packet[i + 1]);
// se non sono il primo
if (!actual_address.equals(first_path_addr)) {
FlowTableEntry rule = new FlowTableEntry();
initRule(rule);
//regola per forwardare indietro
rule.getWindow()[0]
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLocation(SDN_WISE_PACKET);
rule.getWindow()[0].setPos(SDN_WISE_DST_H);
rule.getWindow()[0].setValueHigh(first_path_addr.getHigh());
rule.getWindow()[0].setValueLow(first_path_addr.getLow());
rule.getAction()
.setType(SDN_WISE_FORWARD_UNICAST)
.setLocation(SDN_WISE_PACKET);
rule.getAction().setPos(SDN_WISE_NXHOP_H);
rule.getAction().setValueHigh(packet[i - 2]);
rule.getAction().setValueLow(packet[i - 1]);
//e la imparo
int p = searchRule(rule);
insertRule(rule, p);
}
if (!actual_address.equals(last_path_addr)) {
FlowTableEntry rule = new FlowTableEntry();
initRule(rule);
//regola per forwardare avanti
rule.getWindow()[0]
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLocation(SDN_WISE_PACKET);
rule.getWindow()[0].setPos(SDN_WISE_DST_H);
rule.getWindow()[0].setValueHigh(last_path_addr.getHigh());
rule.getWindow()[0].setValueLow(last_path_addr.getLow());
rule.getAction()
.setType(SDN_WISE_FORWARD_UNICAST)
.setLocation(SDN_WISE_PACKET);
rule.getAction().setPos(SDN_WISE_NXHOP_H);
rule.getAction().setValueHigh(packet[i + 2]);
rule.getAction().setValueLow(packet[i + 3]);
//e la imparo
int p = searchRule(rule);
insertRule(rule, p);
//cambio next hop e dest del pacchetto
packet[SDN_WISE_DST_H] = packet[i + 2];
packet[SDN_WISE_DST_L] = packet[i + 3];
packet[SDN_WISE_NXHOP_H] = packet[i + 2];
packet[SDN_WISE_NXHOP_L] = packet[i + 3];
// e forwardo
radioTX(packet, SDN_WISE_MAC_SEND_UNICAST);
break;
}
}
i += 2;
}
} else {
runFlowMatch(packet);
}
}
void runFlowMatch(int[] packet) {
int j, i, found = 0;
for (j = 0; j < SDN_WISE_RLS_MAX; j++) {
i = getActualFlowIndex(j);
if (matchRule(flowTable.get(i), packet) == 1) {
found = 1;
runAction(flowTable.get(i).getAction(), packet);
flowTable.get(i).getStats().setCounter(flowTable.get(i).getStats().getCounter() + 1);
if (!(flowTable.get(i).getAction().getMultimatch())) {
break;
}
}
}
if (found == 0) { //!found
// It's necessary to send a rule/request if we have done the lookup
// I must modify the source address with myself,
packet[SDN_WISE_SRC_H] = addr.getHigh();
packet[SDN_WISE_SRC_L] = addr.getLow();
// il nuovo tipo è impostato a: il tipo originale + 128
packet[SDN_WISE_TYPE] += 128;
packet[SDN_WISE_TTL] = ttl_max;
// The next hop at the moment will be the best hop to reach the sink
// So, in this case forward the packet
packet[SDN_WISE_NXHOP_H] = flowTable.get(0).getAction().getValueHigh();
packet[SDN_WISE_NXHOP_L] = flowTable.get(0).getAction().getValueLow();
// Send Rule/Request packet
controllerTX(packet);
}
}
abstract void rxCONFIG(int[] packet);
void insertRule(FlowTableEntry rule, int pos) {
if (pos >= SDN_WISE_RLS_MAX) {
pos = flow_table_free_pos; // TODO controllare
flow_table_free_pos++;
if (flow_table_free_pos >= SDN_WISE_RLS_MAX) {
flow_table_free_pos = 1;
}
}
flowTable.set(pos, rule);
}
// Verifica che una condizione di una finestra di una regola è soddisfatta
int matchWindow(FlowTableWindow window, int[] packet) {
int size = window.getSize();
int operatore = window.getOperator();
int matchMemory = window.getLocation();
int[] ptr;
if (matchMemory != 0) {
ptr = packet;
} else {
ptr = statusRegister;
}
switch (size) {
case SDN_WISE_SIZE_2:
return doOperation(operatore,
ptr[window.getPos()] * 256 + ptr[window.getPos() + 1],
window.getValueHigh() * 256 + window.getValueLow());
case SDN_WISE_SIZE_1:
return doOperation(operatore, ptr[window.getPos()], window.getValueLow());
case SDN_WISE_SIZE_0:
return 2;
default:
return 0;
}
}
// Verifica che un pacchetto corrisponda a una regola
int matchRule(FlowTableEntry rule, int[] packet) {
int i;
int sum = 0;
for (i = 0; i < SDN_WISE_WINDOWS_MAX; i++) {
int result = matchWindow(rule.getWindow()[i], packet);
if (result != 0) {
sum += result;
} else {
return 0;
}
}
return (sum == SDN_WISE_WINDOWS_MAX * 2 ? 0 : 1);
}
// Esegue l'azione alla posizione r della tabella
void runAction(FlowTableAction action, int[] packet) {
int i;
int action_type = action.getType();
int action_location = action.getLocation();
switch (action_type) {
case SDN_WISE_FORWARD_UNICAST:
case SDN_WISE_FORWARD_BROADCAST:
packet[SDN_WISE_TTL]--;
packet[action.getPos()] = action.getValueHigh();
packet[action.getPos() + 1] = action.getValueLow();
radioTX(packet, action_type == SDN_WISE_FORWARD_BROADCAST);
break;
case SDN_WISE_DROP:
int prob = action.getValueHigh();
// Se prob di drop=70% significa che se genero un numero,
// droppo il pacchetto se il numero generato è inferiore a 70
if ((Math.random() * 100) > prob) {
// il secondo int indica il secondo int
// dell'indirizzo del nodo a cui forwardare il pacchetto
// il primo int è scelto casualmente, tra i vicini con
// il secondo int dell'indirizzo posto uguale a quello
// contenuto nella rule
int first_byte_address = chooseNeighbor(action.getValueLow());
if (first_byte_address != 254) {
packet[SDN_WISE_TTL]--;
packet[SDN_WISE_NXHOP_H] = first_byte_address;
packet[SDN_WISE_NXHOP_L] = action.getValueHigh();
radioTX(packet, SDN_WISE_MAC_SEND_UNICAST);
}//else
}//else
break;
//case 2
case SDN_WISE_MODIFY:
if (action_location != 0) {
int tmpAct1 = packet[action.getPos()];
int tmpAct2 = packet[action.getPos() + 1];
packet[action.getPos()] = action.getValueHigh();
packet[action.getPos() + 1] = action.getValueLow();
// TODO considerare il caso del multicas quando si inseriscono i int[] nella messageQueue
messageQueue.add(packet);
packet[action.getPos()] = tmpAct1;
packet[action.getPos() + 1] = tmpAct2;
} else {
statusRegister[action.getPos()] = action.getValueHigh();
statusRegister[action.getPos() + 1] = action.getValueLow();
messageQueue.add(packet);
}
break;
case SDN_WISE_AGGREGATE:
// TODO Ancora da definire
break;
case SDN_WISE_FORWARD_UP:
FunctionInterface srvI
= functions.get(action.getValueHigh() * 256 + action.getValueLow());
if (srvI != null) {
srvI.function(
adcRegister,
flowTable,
neighborTable,
statusRegister,
acceptedId,
messageQueue,
new NetworkPacket(packet)
);
}
break;
default:
break;
}//switch
}
int doOperation(int operatore, int item1, int item2) {
switch (operatore) {
case SDN_WISE_EQUAL:
return item1 == item2 ? 1 : 0;
case SDN_WISE_NOT_EQUAL:
return item1 != item2 ? 1 : 0;
case SDN_WISE_BIGGER:
return item1 > item2 ? 1 : 0;
case SDN_WISE_LESS:
return item1 < item2 ? 1 : 0;
case SDN_WISE_EQUAL_OR_BIGGER:
return item1 >= item2 ? 1 : 0;
case SDN_WISE_EQUAL_OR_LESS:
return item1 <= item2 ? 1 : 0;
default:
return 0;
}
}
int searchRule(FlowTableEntry rule) {
int i, j, sum, target;
for (i = 0; i < SDN_WISE_RLS_MAX; i++) {
sum = 0;
target = SDN_WISE_WINDOWS_MAX;
for (j = 0; j < SDN_WISE_WINDOWS_MAX; j++) {
if (flowTable.get(i).getWindow()[j].getOp() == rule.getWindow()[j].getOp()
&& flowTable.get(i).getWindow()[j].getPos() == rule.getWindow()[j].getPos()
&& flowTable.get(i).getWindow()[j].getValueHigh() == rule.getWindow()[j].getValueHigh()
&& flowTable.get(i).getWindow()[j].getValueLow() == rule.getWindow()[j].getValueLow()) {
sum++;
}
}
if (rule.getAction().getMultimatch()) {
target++;
if (flowTable.get(i).getAction().getAct() == rule.getAction().getAct()
&& flowTable.get(i).getAction().getPos() == rule.getAction().getPos()
&& flowTable.get(i).getAction().getValueHigh() == rule.getAction().getValueHigh()
&& flowTable.get(i).getAction().getValueLow() == rule.getAction().getValueLow()) {
sum++;
}
}
if (sum == target) {
return i;
}
}
return SDN_WISE_RLS_MAX + 1;
}
int getNeighborIndex(NodeAddress addr) {
int i;
for (i = 0; i < SDN_WISE_NEIGHBORS_MAX; i++) {
if (neighborTable.get(i).getAddr().equals(addr)) {
return i;
}
if (neighborTable.get(i).getAddr().equals(new NodeAddress(255, 255))) { //se sono uguali
return -1;
}
}
return SDN_WISE_NEIGHBORS_MAX + 1;
}
int searchAcceptedId(int addr) {
int i;
for (i = 0; i < SDN_WISE_ACCEPTED_ID_MAX; i++) {
if (acceptedId.get(i).intValue() == addr) {
return i;
}
}
return SDN_WISE_ACCEPTED_ID_MAX + 1;
}
boolean isAcceptedIdAddress(int addr_h, int addr_l) {
return (addr_h == addr.getHigh()
&& addr_l == addr.getLow())
|| (addr_h == 255 && addr_l == 255)
|| (searchAcceptedId(new NodeAddress(addr_h, addr_l).intValue())
!= SDN_WISE_ACCEPTED_ID_MAX + 1);
}
boolean isAcceptedIdPacket(int[] packet) {
return isAcceptedIdAddress(packet[SDN_WISE_DST_H], packet[SDN_WISE_DST_L]);
}
int getActualFlowIndex(int j) {
//j = j % SDN_WISE_RLS_MAX;
int i;
if (j == 0) {
i = 0;
} else {
i = flow_table_free_pos - j;
if (i == 0) {
i = SDN_WISE_RLS_MAX - 1;
} else if (i < 0) {
i = SDN_WISE_RLS_MAX - 1 + i;
}
}
return i;
}
abstract void SDN_WISE_Callback(int[] packet);
abstract void controllerTX(int[] packetInt);
public void radioTX(int[] packetInt, boolean sdn_wise_mac_send_unicast) {
battery.transmitRadio(packetInt.length);
System.out.println("[N"+ addr.toString() +"]: RTX " + Arrays.toString(packetInt));
NetworkPacket np = new NetworkPacket(packetInt);
NodeAddress tmpNxHop = np.getNxhop();
NodeAddress tmpDst = np.getDst();
if (tmpDst.equals(new NodeAddress("255.255"))) {
for (FakeInfo isa : neighbourList.values()) {
DatagramPacket pck = new DatagramPacket(np.toByteArray(), np.getLen(),
isa.inetAddress.getAddress(), isa.inetAddress.getPort());
try {
socket.send(pck);
} catch (IOException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
}
} else {
FakeInfo isa = neighbourList.get(tmpNxHop);
if (isa != null) {
try {
DatagramPacket pck = new DatagramPacket(np.toByteArray(), np.getLen(),
isa.inetAddress.getAddress(), isa.inetAddress.getPort());
socket.send(pck);
} catch (UnknownHostException ex) {
Logger.getLogger(SensorNode.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SensorNode.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void arraycopy(int[] src, int srcPos, byte[] dst, int dstPos, int len) {
for (int i = 0; i < len; i++) {
dst[dstPos + i] = (byte) src[srcPos + i];
}
}
public void arraycopy(byte[] src, int srcPos, int[] dst, int dstPos, int len) {
for (int i = 0; i < len; i++) {
dst[dstPos + i] = src[srcPos + i];
}
}
public FunctionInterface createServiceInterface(byte[] classFile) {
CustomClassLoader cl = new CustomClassLoader();
FunctionInterface srvI = null;
Class service = cl.defClass(classFile, classFile.length);
try {
srvI = (FunctionInterface) service.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
return srvI;
}
private class FakeInfo {
InetSocketAddress inetAddress;
int rssi;
FakeInfo(InetSocketAddress inetAddress, int rssi) {
this.inetAddress = inetAddress;
this.rssi = rssi;
}
}
private class Task extends TimerTask {
private int cntBeacon;
private int cntReport;
private int cntUpdTable;
@Override
public void run() {
if (semaphore == 1) {
battery.keepAlive(1);
cntBeacon++;
cntReport++;
//cntUpdTable++; // TODO IMBRACCHIO!!!!!!
if ((cntBeacon) >= cnt_beacon_max) {
cntBeacon = 0;
txBEACON();
}
if ((cntReport) >= cnt_report_max) {
cntReport = 0;
txREPORT();
}
if ((cntUpdTable) >= cnt_updtable_max) {
cntUpdTable = 0;
updateTable();
}
}
}
}
private class PacketManager implements Runnable {
@Override
public void run() {
try {
while (true) {
int rssi;
int[] tmp = messageQueue.take();
NetworkPacket tmpPacket = new NetworkPacket(tmp);
FakeInfo fk = neighbourList.get(tmpPacket.getSrc());
if (fk != null) {
rssi = fk.rssi;
} else {
rssi = 255;
}
battery.receiveRadio(tmp.length);
rxHandler(tmp, rssi);
}
} catch (InterruptedException ex) {
Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void rxHandler(int[] packet, int rssi) throws InterruptedException {
System.out.println("[N"+ addr.toString() +"]: RRX " + Arrays.toString(packet));
if (packet[SDN_WISE_LEN] > SDN_WISE_DFLT_HDR_LEN
&& packet[SDN_WISE_NET_ID] == net_id
&& packet[SDN_WISE_TTL] != 0) {
switch (packet[SDN_WISE_TYPE]) {
case SDN_WISE_DATA:
rxDATA(packet);
break;
case SDN_WISE_BEACON:
rxBEACON(packet, rssi);
break;
case SDN_WISE_RESPONSE:
rxRESPONSE(packet);
break;
case SDN_WISE_OPEN_PATH:
rxOPEN_PATH(packet);
break;
case SDN_WISE_CONFIG:
rxCONFIG(packet);
break;
default:
rxREPORT(packet);
break;
}// fine switch sul type
}// fine if sull'address
}
}
private class CustomClassLoader extends ClassLoader {
public Class defClass(byte[] data, int len) {
return defineClass(null, data, 0, len);
}
}
}