X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iot2.git;a=blobdiff_plain;f=iotjava%2Fiotruntime%2Fmaster%2FIoTMaster.java;h=bd69b0ac82f842d6839adf1055f71d1af292fec1;hp=7bd6ed87dfd51a71204bd9fafd9dba85c20b8c4f;hb=d227810e27d0c63637497c4adaabc19dc67b186a;hpb=2b186a1e156bfd023b55a0053bd46df4376cce44 diff --git a/iotjava/iotruntime/master/IoTMaster.java b/iotjava/iotruntime/master/IoTMaster.java index 7bd6ed8..bd69b0a 100644 --- a/iotjava/iotruntime/master/IoTMaster.java +++ b/iotjava/iotruntime/master/IoTMaster.java @@ -19,6 +19,7 @@ import java.io.InputStreamReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.OutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.IOException; @@ -27,6 +28,7 @@ import java.lang.Class; import java.lang.reflect.*; import java.net.Socket; import java.net.ServerSocket; +import java.nio.ByteBuffer; import java.util.*; import static java.lang.Math.toIntExact; @@ -38,7 +40,7 @@ import static java.lang.Math.toIntExact; * @version 1.0 * @since 2016-06-16 */ -public class IoTMaster { +public final class IoTMaster { /** * IoTMaster class properties @@ -49,10 +51,13 @@ public class IoTMaster { private CommunicationHandler commHan; private LoadBalancer lbIoT; private RouterConfig routerConfig; + private ProcessJailConfig processJailConfig; private ObjectInitHandler objInitHand; private ObjectAddressInitHandler objAddInitHand; private String[] strObjectNames; - private Map mapClassNameToCrim; + // Now this can be either ClassRuntimeInstrumenterMaster or CRuntimeInstrumenterMaster + private Map mapClassNameToCrim; + /** * These properties hold information of a certain object * at a certain time @@ -68,21 +73,35 @@ public class IoTMaster { private Object[] arrFieldValues; private Socket filesocket; + /** + * For connection with C++ IoTSlave + */ + private ServerSocket serverSocketCpp; + private Socket socketCpp; + private BufferedInputStream inputCpp; + private BufferedOutputStream outputCpp; + // Constants that are to be extracted from config file private static String STR_MASTER_MAC_ADD; private static String STR_IOT_CODE_PATH; private static String STR_CONT_PATH; private static String STR_RUNTIME_DIR; + private static String STR_SLAVE_DIR; private static String STR_CLS_PATH; private static String STR_RMI_PATH; private static String STR_RMI_HOSTNAME; private static String STR_LOG_FILE_PATH; - private static String STR_SSH_USERNAME; + private static String STR_USERNAME; private static String STR_ROUTER_ADD; private static String STR_MONITORING_HOST; private static String STR_ZB_GATEWAY_ADDRESS; private static String STR_ZB_GATEWAY_PORT; private static String STR_ZB_IOTMASTER_PORT; + private static String STR_JVM_INIT_HEAP_SIZE; + private static String STR_JVM_MAX_HEAP_SIZE; + private static String STR_LANGUAGE_CONTROLLER; + private static String STR_SKEL_CLASS_SUFFIX; + private static String STR_STUB_CLASS_SUFFIX; private static boolean BOOL_VERBOSE; /** @@ -94,6 +113,9 @@ public class IoTMaster { private static final String STR_CFG_FILE_EXT = ".config"; private static final String STR_CLS_FILE_EXT = ".class"; private static final String STR_JAR_FILE_EXT = ".jar"; + private static final String STR_MAC_POLICY_EXT = ".tomoyo.pol"; + private static final String STR_SHELL_FILE_EXT = ".sh"; + private static final String STR_SO_FILE_EXT = ".so"; private static final String STR_ZIP_FILE_EXT = ".zip"; private static final String STR_TCP_PROTOCOL = "tcp"; private static final String STR_UDP_PROTOCOL = "udp"; @@ -103,8 +125,20 @@ public class IoTMaster { private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS"; private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS"; private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE"; + private static final String STR_LANGUAGE = "LANGUAGE"; private static final String STR_YES = "Yes"; private static final String STR_NO = "No"; + private static final String STR_JAVA = "Java"; + private static final String STR_CPP = "C++"; + private static final String STR_SSH = "ssh"; + private static final String STR_SCP = "scp"; + private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o"; + private static final String STR_SHELL_HEADER = "#!/bin/sh"; + private static final String STR_JAVA_PATH = "/usr/bin/java"; + private static final String STR_MAC_POL_PATH = "tomoyo/"; + + private static int INT_SIZE = 4; // send length in the size of integer (4 bytes) + private static final int INT_DNS_PORT = 53; /** * Runtime class name constants - not to be configured by users @@ -125,6 +159,7 @@ public class IoTMaster { commHan = null; lbIoT = null; routerConfig = null; + processJailConfig = null; objInitHand = null; objAddInitHand = null; strObjectNames = argObjNms; @@ -139,21 +174,30 @@ public class IoTMaster { arrFieldValues = null; filesocket = null; mapClassNameToCrim = null; + // Connection with C++ IoTSlave + serverSocketCpp = null; + socketCpp = null; + inputCpp = null; + outputCpp = null; STR_MASTER_MAC_ADD = null; STR_IOT_CODE_PATH = null; STR_CONT_PATH = null; STR_RUNTIME_DIR = null; + STR_SLAVE_DIR = null; STR_CLS_PATH = null; STR_RMI_PATH = null; STR_RMI_HOSTNAME = null; STR_LOG_FILE_PATH = null; - STR_SSH_USERNAME = null; + STR_USERNAME = null; STR_ROUTER_ADD = null; STR_MONITORING_HOST = null; STR_ZB_GATEWAY_ADDRESS = null; STR_ZB_GATEWAY_PORT = null; STR_ZB_IOTMASTER_PORT = null; + STR_JVM_INIT_HEAP_SIZE = null; + STR_JVM_MAX_HEAP_SIZE = null; + STR_LANGUAGE_CONTROLLER = null; BOOL_VERBOSE = false; } @@ -169,9 +213,29 @@ public class IoTMaster { lbIoT.setupLoadBalancer(); routerConfig = new RouterConfig(); routerConfig.getAddressList(STR_ROUTER_ADD); + processJailConfig = new ProcessJailConfig(); + //processJailConfig.setAddressListObject(routerConfig.getAddressListObject()); objInitHand = new ObjectInitHandler(BOOL_VERBOSE); objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE); - mapClassNameToCrim = new HashMap(); + mapClassNameToCrim = new HashMap(); + } + + /** + * getPrintWriter() gets a new PrintWriter for a new object + * + * @param strObjectName String object name + * @return PrintWriter + */ + private PrintWriter getPrintWriter(String strObjectName) { + + FileWriter fw = null; + try { + fw = new FileWriter(strObjectName); + } catch (IOException ex) { + ex.printStackTrace(); + } + PrintWriter printWriter = new PrintWriter(new BufferedWriter(fw)); + return printWriter; } /** @@ -198,16 +262,21 @@ public class IoTMaster { STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH"); STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH"); STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR"); + STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR"); STR_CLS_PATH = prop.getProperty("CLASS_PATH"); STR_RMI_PATH = prop.getProperty("RMI_PATH"); STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME"); STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH"); - STR_SSH_USERNAME = prop.getProperty("SSH_USERNAME"); + STR_USERNAME = prop.getProperty("USERNAME"); STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD"); STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST"); STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS"); STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT"); STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT"); + STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE"); + STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE"); + STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX"); + STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX"); if(prop.getProperty("VERBOSE").equals(STR_YES)) { BOOL_VERBOSE = true; } @@ -217,16 +286,21 @@ public class IoTMaster { RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE); RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE); RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE); + RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE); RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE); RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE); RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE); RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE); - RuntimeOutput.print("STR_SSH_USERNAME=" + STR_SSH_USERNAME, BOOL_VERBOSE); + RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE); RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE); RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE); RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE); RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE); RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE); + RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE); + RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE); + RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE); + RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE); RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE); RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE); } @@ -307,14 +381,16 @@ public class IoTMaster { * @return void */ private void commMasterToSlave(Message msgSend, String strPurpose, - ObjectInputStream inStream, ObjectOutputStream outStream) + InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException { // Send message/command from master + ObjectOutputStream outStream = (ObjectOutputStream) _outStream; outStream.writeObject(msgSend); RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE); // Get reply from slave as acknowledgment + ObjectInputStream inStream = (ObjectInputStream) _inStream; Message msgReply = (Message) inStream.readObject(); RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); } @@ -327,17 +403,21 @@ public class IoTMaster { * @params strIoTSlaveObjectHostAdd String slave host address * @params inStream ObjectInputStream communication * @params inStream ObjectOutputStream communication + * @params strLanguage String language * @return void */ - private void instrumentIoTSetDevice(String strFieldIdentifier, String strFieldName, String strIoTSlaveObjectHostAdd, - ObjectInputStream inStream, ObjectOutputStream outStream) + private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd, + InputStream inStream, OutputStream outStream, String strLanguage) throws IOException, ClassNotFoundException, InterruptedException { // Get information from the set List listObject = objAddInitHand.getFields(strFieldIdentifier); // Create a new IoTSet - Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName); - commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream); + if(strLanguage.equals(STR_JAVA)) { + Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName); + commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream); + } else + createNewIoTSetCpp(strFieldName, outStream, inStream); int iRows = listObject.size(); RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE); // Transfer the address @@ -345,10 +425,13 @@ public class IoTMaster { arrFieldValues = listObject.get(iRow); // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self) String strDeviceAddress = null; + String strDeviceAddressKey = null; if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) { strDeviceAddress = strIoTSlaveObjectHostAdd; + strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd; } else { strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]); + strDeviceAddressKey = strObjName + "-" + strDeviceAddress; } int iDestDeviceDriverPort = (int) arrFieldValues[1]; String strProtocol = (String) arrFieldValues[2]; @@ -360,18 +443,35 @@ public class IoTMaster { bDstPortWildCard = (boolean) arrFieldValues[4]; } // Add the port connection into communication handler - if it's not assigned yet - if (commHan.getComPort(strDeviceAddress) == null) { - commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress); + if (commHan.getComPort(strDeviceAddressKey) == null) { + commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey); } + + // TODO: DEBUG!!! + System.out.println("\n\n DEBUG: InstrumentSetDevice: Object Name: " + strObjName); + System.out.println("DEBUG: InstrumentSetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey)); + System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n"); + // Send address one by one - Message msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, - strDeviceAddress, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort, - bSrcPortWildCard, bDstPortWildCard); - commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream); + if(strLanguage.equals(STR_JAVA)) { + Message msgGetIoTSetObj = null; + if (bDstPortWildCard) { + String strUniqueDev = strDeviceAddressKey + ":" + iRow; + msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, + strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard); + } else + msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, + strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard); + commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream); + } else + getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, + bSrcPortWildCard, bDstPortWildCard); } // Reinitialize IoTSet on device object - commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), - "Reinitialize IoTSet fields!", inStream, outStream); + if(strLanguage.equals(STR_JAVA)) + commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream); + else + reinitializeIoTSetFieldCpp(outStream, inStream); } @@ -383,46 +483,58 @@ public class IoTMaster { * @params strIoTSlaveObjectHostAdd String slave host address * @params inStream ObjectInputStream communication * @params inStream ObjectOutputStream communication + * @params strLanguage String language * @return void */ - private void instrumentIoTSetZBDevice(Map.Entry map, String strFieldName, String strIoTSlaveObjectHostAdd, - ObjectInputStream inStream, ObjectOutputStream outStream) + private void instrumentIoTSetZBDevice(Map.Entry map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd, + InputStream inStream, OutputStream outStream, String strLanguage) throws IOException, ClassNotFoundException, InterruptedException { // Get information from the set SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue(); // Create a new IoTSet - Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName); - commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream); + if(strLanguage.equals(STR_JAVA)) { + Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName); + commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream); + } else // TODO: will need to implement IoTSet Zigbee for C++ later + ; // Prepare ZigbeeConfig String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS); + String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress; int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT); int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT); commHan.addDevicePort(iZigbeeIoTMasterPort); ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort, BOOL_VERBOSE); // Add the port connection into communication handler - if it's not assigned yet - if (commHan.getComPort(strZigbeeGWAddress) == null) { - commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddress); + if (commHan.getComPort(strZigbeeGWAddressKey) == null) { + commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey); } int iRows = setInstrumenter.numberOfRows(); RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE); + + // TODO: DEBUG!!! + System.out.println("\n\nDEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName); + System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey)); + System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n"); + // Transfer the address for(int iRow=0; iRow listObject = objAddInitHand.getFields(strFieldIdentifier); // Create a new IoTSet - Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName); - commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream); + if(strLanguage.equals(STR_JAVA)) { + Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName); + commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream); + } else + ; int iRows = listObject.size(); RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE); // Transfer the address @@ -452,9 +568,11 @@ public class IoTMaster { // Get device address String strAddress = (String) arrFieldValues[0]; // Send address one by one - Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, - strAddress); - commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream); + if(strLanguage.equals(STR_JAVA)) { + Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress); + commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream); + } else // TODO: Implement IoTSet Address for C++ + ; } // Reinitialize IoTSet on device object commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), @@ -465,15 +583,17 @@ public class IoTMaster { /** * A private method to instrument an object on a specific machine and setting up policies * - * @params strFieldObjectID String field object ID + * @params strFieldObjectID String field object ID + * @params strObjControllerName String object controller name + * @params strLanguage String language * @return void */ - private void instrumentObject(String strFieldObjectID) throws IOException { + private void instrumentObject(String strFieldObjectID, String strObjControllerName, String strLanguage) throws IOException { // Extract the interface name for RMI // e.g. ProximitySensorInterface, TempSensorInterface, etc. -String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT; + String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT; strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG); strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG); // Create an object name, e.g. ProximitySensorImplPS1 @@ -513,8 +633,16 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL); routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL); + // Configure MAC policies for objects + //String strFileName = STR_MAC_POL_PATH + strObjClassName + STR_MAC_POLICY_EXT; + String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT; + processJailConfig.configureProcessJailDeviceDriverPolicies(strIoTSlaveObjectHostAdd, strObjName, strObjClassName, + strFileName, strIoTMasterHostAdd, commHan.getComPort(strObjName), commHan.getRMIRegPort(strObjName), + commHan.getRMIStubPort(strObjName)); + processJailConfig.configureProcessJailContRMIPolicies(strObjControllerName, strIoTSlaveObjectHostAdd, + commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName)); // Instrument the IoTSet declarations inside the class file - instrumentObjectIoTSet(strFieldObjectID); + instrumentObjectIoTSet(strFieldObjectID, strLanguage); } // Send routing policy to router for controller object // ROUTING POLICY: RMI communication - RMI registry and stub ports @@ -533,6 +661,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName)); } + /** * A private method to set router policies for IoTDeviceAddress objects * @@ -554,28 +683,43 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self) String strDeviceAddress = null; + String strDeviceAddressKey = null; if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) { strDeviceAddress = strIoTSlaveObjectHostAdd; - } else { + strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd; + } else { // Concatenate object name and IP address to give unique key - for a case where there is one device for multiple drivers strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]); + strDeviceAddressKey = strObjName + "-" + strDeviceAddress; } int iDestDeviceDriverPort = (int) arrFieldValues[1]; String strProtocol = (String) arrFieldValues[2]; // Add the port connection into communication handler - if it's not assigned yet - if (commHan.getComPort(strDeviceAddress) == null) { - commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress); + if (commHan.getComPort(strDeviceAddressKey) == null) + commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey); + boolean bDstPortWildCard = false; + // Recognize this and allocate different ports for it + if (arrFieldValues.length > 3) { + bDstPortWildCard = (boolean) arrFieldValues[4]; + if (bDstPortWildCard) { // This needs a unique source port + String strUniqueDev = strDeviceAddressKey + ":" + iRow; + commHan.addAdditionalPort(strUniqueDev); + } } + + // TODO: DEBUG!!! + System.out.println("\n\n DEBUG: InstrumentPolicySetDevice: Object Name: " + strObjName); + System.out.println("DEBUG: InstrumentPolicySetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey)); + System.out.println("DEBUG: InstrumentPolicySetDevice: Device address: " + strDeviceAddressKey + "\n\n"); + // Send routing policy to router for device drivers and devices // ROUTING POLICY: RMI communication - RMI registry and stub ports if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) { // Port number -1 means that we don't set the policy strictly to port number level // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well) // ROUTING POLICY: Device driver and device - routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, - strProtocol); + routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol); // ROUTING POLICY: Send to the compute node where the device driver is - routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, - strDeviceAddress, strProtocol); + routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol); } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) { routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress); routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress); @@ -583,19 +727,22 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // This is a TCP protocol that connects, e.g. a phone to our runtime system // that provides a gateway access (accessed through destination port number) commHan.addDevicePort(iDestDeviceDriverPort); - routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, - STR_TCP_PROTOCOL, iDestDeviceDriverPort); - routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, - STR_TCP_PROTOCOL, iDestDeviceDriverPort); + routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort); + routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort); routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress); routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress); + // Configure MAC policies + processJailConfig.configureProcessJailGWDevicePolicies(strIoTSlaveObjectHostAdd, STR_ROUTER_ADD, INT_DNS_PORT); } else { // Other port numbers... commHan.addDevicePort(iDestDeviceDriverPort); - routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, - strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort); - routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, - strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort); + routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol, + commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort); + routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol, + commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort); + // Configure MAC policies + processJailConfig.configureProcessJailDevicePolicies(strIoTSlaveObjectHostAdd, strProtocol, + commHan.getComPort(strDeviceAddressKey), strDeviceAddress, iDestDeviceDriverPort); } } } @@ -609,7 +756,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa * @return void */ private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry map, - String strHostAddress) { + String strHostAddress, String strControllerName) { // Get information from the set SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue(); @@ -622,6 +769,11 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // Get device address String strAddress = (String) arrFieldValues[0]; // Setting up router policies for HTTP/HTTPs + if (strControllerName != null) { + processJailConfig.configureProcessJailInetAddressPolicies(strControllerName, strAddress); + } else { + processJailConfig.configureProcessJailInetAddressPolicies(strHostAddress, strAddress); + } routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress); routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress); } @@ -632,28 +784,37 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa *

* Mostly the IoTSet fields would contain IoTDeviceAddress objects * - * @params strFieldObjectID String field object ID + * @params strFieldObjectID String field object ID + * @params strLanguage String language * @return void */ - private void instrumentObjectIoTSet(String strFieldObjectID) throws IOException { + private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException { // If this is a new object ... then create one // Instrument the class source code and look for IoTSet for device addresses // e.g. @config private IoTSet lb_addresses; - String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT; - FileInputStream fis = new FileInputStream(strObjectClassNamePath); - ClassReader cr = new ClassReader(fis); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - // We need Object ID to instrument IoTDeviceAddress - ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE); - cr.accept(crim, 0); - fis.close(); - RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " + - strFieldObjectID, BOOL_VERBOSE); + HashMap hmObjectFieldObjects = null; + if(strLanguage.equals(STR_JAVA)) { + String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT; + FileInputStream fis = new FileInputStream(strObjectClassNamePath); + ClassReader cr = new ClassReader(fis); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + // We need Object ID to instrument IoTDeviceAddress + ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE); + cr.accept(crim, 0); + fis.close(); + mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim); + hmObjectFieldObjects = crim.getFieldObjects(); + } else { // For C++ + String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT; + CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE); + mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim); + hmObjectFieldObjects = crim.getFieldObjects(); + } // Get the object and the class names // Build objects for IoTSet and IoTRelation fields in the device object classes - mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim); - HashMap hmObjectFieldObjects = crim.getFieldObjects(); + RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " + + strFieldObjectID, BOOL_VERBOSE); for(Map.Entry map : hmObjectFieldObjects.entrySet()) { RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE); // Iterate over HashMap and choose between processing @@ -667,7 +828,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd); } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { // Instrument the IoTAddress - setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd); + setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd, null); } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { // Instrument the IoTZigbeeAddress - special feature for Zigbee device support RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..", @@ -686,6 +847,122 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa } + /** + * A private method to send files to a Java slave driver + * + * @params serverSocket ServerSocket + * @params _inStream InputStream + * @params _outStream OutputStream + * @params strObjName String + * @params strObjClassName String + * @params strObjClassInterfaceName String + * @params strObjStubClsIntfaceName String + * @params strIoTSlaveObjectHostAdd String + * @params strFieldObjectID String + * @params arrFieldValues Object[] + * @params arrFieldClasses Class[] + * @return void + */ + private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream, + String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName, + String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses) + throws IOException, ClassNotFoundException { + + ObjectInputStream inStream = (ObjectInputStream) _inStream; + ObjectOutputStream outStream = (ObjectOutputStream) _outStream; + // Create message to transfer file first + String sFileName = strObjClassName + STR_JAR_FILE_EXT; + String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName; + File file = new File(sPath); + commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()), + "Sending file!", inStream, outStream); + // Send file - JAR file for object creation + sendFile(serverSocket.accept(), sPath, file.length()); + Message msgReply = (Message) inStream.readObject(); + RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); + // Pack object information to create object on a IoTSlave + Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd, + strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), + commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses); + // Send message + commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream); + } + + + /** + * A private method to send files to a Java slave driver + * + * @return void + */ + private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd) + throws IOException, ClassNotFoundException { + + // Create message to transfer file first + String sFileName = strObjClassName + STR_ZIP_FILE_EXT; + String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName; + String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR; + runCommand(strCmdSend); + RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE); + // Unzip file + String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + + STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";"; + runCommand(strCmdUnzip); + RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE); + + } + + + /** + * Construct command line for Java IoTSlave + * + * @return String + */ + private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) { + + // Create an Shell executable + String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + + STR_RMI_HOSTNAME + strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " + + commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " + + commHan.getRMIStubPort(strObjName) + " > " + STR_LOG_FILE_PATH + strObjName + ".log &"; + String shellFile = "./" + strObjName + STR_SHELL_FILE_EXT; + createWrapperShellScript(strJavaCommand, shellFile); + // Send the file to the compute node + String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_RUNTIME_DIR; + runCommand(strCmdSend); + System.out.println("IoTMaster: Sending shell file: " + strCmdSend); + return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile; + } + + + /** + * Construct command line for C++ IoTSlave + * + * @return String + */ + private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) { + + return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + + STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " + + commHan.getComPort(strObjName) + " " + strObjName; + } + + + /** + * createWrapperShellScript() gets a wrapper shell script + * + * @param strCommand String command + * @param strObjectName String object name + * @return PrintWriter + */ + private void createWrapperShellScript(String strCommand, String strFileName) { + + PrintWriter printWriter = getPrintWriter(strFileName); + printWriter.println(strCommand); + printWriter.close(); + runCommand("chmod 755 " + strFileName); + } + + /** * A private method to create an object on a specific machine * @@ -702,10 +979,16 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses) throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException { + // Read config file + String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT; + String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName); + if(strLanguageDriver == null) // Read just the field LANGUAGE if the first read is null + strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE); + if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null + throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile); // PROFILING long start = 0; long result = 0; - // PROFILING start = System.currentTimeMillis(); @@ -715,18 +998,32 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // -Djava.rmi.server.codebase=file:./*.jar // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 & // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa - String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " + - STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME + - strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " + - commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " + - commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &"; + String strSSHCommand = null; + if(strLanguageDriver.equals(STR_JAVA)) + strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName); + else if(strLanguageDriver.equals(STR_CPP)) + strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName); + else + throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver); + RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE); + RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE); // Start a new thread to start a new JVM createThread(strSSHCommand); ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName)); Socket socket = serverSocket.accept(); - ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream()); - ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream()); + //InputStream inStream = new ObjectInputStream(socket.getInputStream()); + //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream()); + InputStream inStream = null; + OutputStream outStream = null; + if(strLanguageDriver.equals(STR_JAVA)) { + inStream = new ObjectInputStream(socket.getInputStream()); + outStream = new ObjectOutputStream(socket.getOutputStream()); + } else { // At this point the language is certainly C++, otherwise would've complained above + inStream = new BufferedInputStream(socket.getInputStream()); + outStream = new BufferedOutputStream(socket.getOutputStream()); + recvAck(inStream); + } // PROFILING result = System.currentTimeMillis()-start; @@ -735,16 +1032,16 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // PROFILING start = System.currentTimeMillis(); - // Create message to transfer file first - String sFileName = strObjClassName + STR_JAR_FILE_EXT; - String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName; - File file = new File(sPath); - commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()), - "Sending file!", inStream, outStream); - // Send file - JAR file for object creation - sendFile(serverSocket.accept(), sPath, file.length()); - Message msgReply = (Message) inStream.readObject(); - RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); + if(strLanguageDriver.equals(STR_JAVA)) { + sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName, + strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, + strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses); + } else { + sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd); + createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd, + commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses, + outStream, inStream); + } // PROFILING result = System.currentTimeMillis()-start; @@ -753,20 +1050,20 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // PROFILING start = System.currentTimeMillis(); - // Pack object information to create object on a IoTSlave - Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd, - strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), - commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses); - // Send message - commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream); // Instrument the class source code and look for IoTSet for device addresses // e.g. @config private IoTSet lb_addresses; - RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + - strFieldObjectID, BOOL_VERBOSE); + RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE); // Get the object and the class names // Build objects for IoTSet and IoTRelation fields in the device object classes - ClassRuntimeInstrumenterMaster crim = mapClassNameToCrim.get(strObjClassName + strFieldObjectID); - HashMap hmObjectFieldObjects = crim.getFieldObjects(); + Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID); + HashMap hmObjectFieldObjects = null; + if (crimObj instanceof ClassRuntimeInstrumenterMaster) { + ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj; + hmObjectFieldObjects = crim.getFieldObjects(); + } else if (crimObj instanceof CRuntimeInstrumenterMaster) { + CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj; + hmObjectFieldObjects = crim.getFieldObjects(); + } for(Map.Entry map : hmObjectFieldObjects.entrySet()) { RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE); // Iterate over HashMap and choose between processing @@ -778,21 +1075,20 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) { // Instrument the normal IoTDeviceAddress synchronized(this) { - instrumentIoTSetDevice(strFieldIdentifier, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream); + instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver); } } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { // Instrument the IoTZigbeeAddress - special feature for Zigbee device support synchronized(this) { - instrumentIoTSetZBDevice(map, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream); + instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver); } } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { // Instrument the IoTAddress synchronized(this) { - instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream); + instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver); } } else { - String strErrMsg = "IoTMaster: Device driver object" + - " can only have IoTSet, IoTSet," + + String strErrMsg = "IoTMaster: Device driver object can only have IoTSet, IoTSet," + " or IoTSet!"; throw new Error(strErrMsg); } @@ -803,7 +1099,13 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa } // End the session // TODO: Change this later - outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION)); + if(strLanguageDriver.equals(STR_JAVA)) { + ObjectOutputStream oStream = (ObjectOutputStream) outStream; + oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION)); + } else { // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread) + createDriverObjectCpp(outStream, inStream); + //endSessionCpp(outStream); + } // PROFILING result = System.currentTimeMillis()-start; @@ -822,7 +1124,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa * * @return void */ - private void createControllerObjects() throws InterruptedException { + private void createDriverObjects() throws InterruptedException { // Create a list of threads List threads = new ArrayList(); @@ -866,9 +1168,10 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa * * @params Map.Entry Entry of map IoTSet instrumentation * @params strFieldName String field name + * @params strLanguage String language * @return void */ - private void instrumentIoTSet(Map.Entry map, String strFieldName) + private void instrumentIoTSet(Map.Entry map, String strFieldName, String strObjControllerName, String strLanguage) throws IOException, ClassNotFoundException, InterruptedException { // Get information from the set @@ -884,7 +1187,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa String strObjID = setInstrumenter.fieldObjectID(iRow); strObjClassName = setInstrumenter.fieldEntryType(strObjID); // Call the method to create an object - instrumentObject(strObjID); + instrumentObject(strObjID, strObjControllerName, strLanguage); objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName, strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName)); @@ -897,9 +1200,10 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa * * @params Map.Entry Entry of map IoTRelation instrumentation * @params strFieldName String field name + * @params strLanguage String language * @return void */ - private void instrumentIoTRelation(Map.Entry map, String strFieldName) + private void instrumentIoTRelation(Map.Entry map, String strFieldName, String strObjControllerName, String strLanguage) throws IOException, ClassNotFoundException, InterruptedException { // Get information from the set @@ -914,7 +1218,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa String strObjID = relationInstrumenter.firstFieldObjectID(iRow); strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID); // Call the method to create an object - instrumentObject(strObjID); + instrumentObject(strObjID, strObjControllerName, strLanguage); // Get the first object controller host address String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd; objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName, @@ -926,13 +1230,12 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa strObjID = relationInstrumenter.secondFieldObjectID(iRow); strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID); // Call the method to create an object - instrumentObject(strObjID); + instrumentObject(strObjID, strObjControllerName, strLanguage); // Get the second object controller host address String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd; objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName, strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName)); - // ROUTING POLICY: first and second controller objects in IoTRelation routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd, strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL); @@ -951,7 +1254,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa * @params outStream ObjectOutputStream communication * @return void */ - private void initializeSetsAndRelations(ObjectInputStream inStream, ObjectOutputStream outStream) + private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream) throws IOException, ClassNotFoundException { // Get list of fields List strFields = objInitHand.getListOfFields(); @@ -968,7 +1271,8 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()), - "Get IoTSet object!", inStream, outStream); + "Get IoTSet object!", inStream, outStream); + } // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), @@ -991,7 +1295,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT) commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(), - objSecObj.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(), + objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(), objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()), "Get IoTRelation second object!", inStream, outStream); } @@ -1002,6 +1306,56 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa } } + /** + * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information + * + * @params inStream ObjectInputStream communication + * @params outStream ObjectOutputStream communication + * @return void + */ + private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream) + throws IOException, ClassNotFoundException { + // Get list of fields + List strFields = objInitHand.getListOfFields(); + // Iterate on HostAddress + for(String str : strFields) { + IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str); + if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) { + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET + createNewIoTSetCpp(str, outStream, inStream); + List listObject = objInitHand.getListObjectInitInfo(str); + for (ObjectInitInfo objInitInfo : listObject) { + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET + getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), + objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(), + objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream); + } + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD + reinitializeIoTSetFieldCpp(outStream, inStream); + } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) { + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION + // TODO: createNewIoTRelation needs to be created here! + createNewIoTRelationCpp(str, outStream, inStream); + List listObject = objInitHand.getListObjectInitInfo(str); + List listSecondObject = objInitHand.getSecondObjectInitInfo(str); + Iterator it = listSecondObject.iterator(); + for (ObjectInitInfo objInitInfo : listObject) { + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT) + getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), + objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(), + objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream); + ObjectInitInfo objSecObj = (ObjectInitInfo) it.next(); + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT) + getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), + objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(), + objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream); + } + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD + reinitializeIoTRelationFieldCpp(outStream, inStream); + } + } + } + /** * A method to set router basic policies at once * @@ -1089,6 +1443,524 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa } } + /** + * A method to create a thread for policy deployment + * + * @param setHostAddresses Set of strings for host addresses to configure + * @return void + */ + private void createMACPolicyThreads(Set setHostAddresses) throws IOException { + + // Create a list of threads + List threads = new ArrayList(); + // Start threads for hosts + for(String strAddress : setHostAddresses) { + Thread policyThread = new Thread(new Runnable() { + public void run() { + synchronized(this) { + processJailConfig.sendMACPolicies(strAddress); + } + } + }); + threads.add(policyThread); + policyThread.start(); + RuntimeOutput.print("Deploying MAC policies for: " + strAddress, BOOL_VERBOSE); + } + // Join all threads + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + + + /** + * A method to send files to Java IoTSlave + * + * @params strObjControllerName String + * @params serverSocket ServerSocket + * @params inStream ObjectInputStream communication + * @params outStream ObjectOutputStream communication + * @return void + */ + private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket, + InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException { + + ObjectInputStream inStream = (ObjectInputStream) _inStream; + ObjectOutputStream outStream = (ObjectOutputStream) _outStream; + // Send .jar file + String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT; + String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" + + strControllerJarName; + File file = new File(strControllerJarNamePath); + commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()), + "Sending file!", inStream, outStream); + // Send file - Class file for object creation + sendFile(serverSocket.accept(), strControllerJarNamePath, file.length()); + Message msgReply = (Message) inStream.readObject(); + RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); + // Send .zip file if additional zip file is specified + String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT; + String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile; + String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG); + if (strAdditionalFile.equals(STR_YES)) { + String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT; + String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" + + strControllerCmpName; + file = new File(strControllerCmpNamePath); + commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()), + "Sending file!", inStream, outStream); + // Send file - Class file for object creation + sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length()); + msgReply = (Message) inStream.readObject(); + RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); + } + } + + + /** + * A method to send files to C++ IoTSlave + * + * @return void + * TODO: Need to look into this (as of now, file transferred retains the "data" format, + * hence it is unreadable from outside world + */ + private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket, + InputStream inStream, OutputStream outStream) throws IOException { + + sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream); + // Send file name + sendString(sFileName, outStream); recvAck(inStream); + File file = new File(sFilePath + sFileName); + int iFileLen = toIntExact(file.length()); + RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE); + // Send file length + sendInteger(iFileLen, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE); + byte[] bytFile = new byte[iFileLen]; + InputStream inFileStream = new FileInputStream(file); + RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE); + + OutputStream outFileStream = fileSocket.getOutputStream(); + RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE); + int iCount; + while ((iCount = inFileStream.read(bytFile)) > 0) { + outFileStream.write(bytFile, 0, iCount); + } + RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE); + recvAck(inStream); + } + + + /** + * A method to send files to C++ IoTSlave (now master using Process() to start + * file transfer using scp) + * + * @return void + */ + private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException { + + // Construct shell command to transfer file + String sFile = sFilePath + sFileName; + String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR; + runCommand(strCmdSend); + RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE); + // Unzip file + String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + + STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";"; + runCommand(strCmdUnzip); + RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE); + } + + + /** + * runCommand() method runs shell command + * + * @param strCommand String that contains command line + * @return void + */ + private void runCommand(String strCommand) { + + try { + Runtime runtime = Runtime.getRuntime(); + Process process = runtime.exec(strCommand); + process.waitFor(); + } catch (IOException ex) { + System.out.println("RouterConfig: IOException: " + ex.getMessage()); + ex.printStackTrace(); + } catch (InterruptedException ex) { + System.out.println("RouterConfig: InterruptException: " + ex.getMessage()); + ex.printStackTrace(); + } + } + + + /** + * Construct command line for Java IoTSlave + * + * @return String + */ + private String getCmdJavaIoTSlave(String strObjControllerName) { + + // Create an Shell executable + String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_JVM_INIT_HEAP_SIZE + " " + + STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + + strIoTMasterHostAdd + " " + commHan.getComPort(strObjControllerName) + " " + + commHan.getRMIRegPort(strObjControllerName) + " " + commHan.getRMIStubPort(strObjControllerName) + + " > " + STR_LOG_FILE_PATH + strObjControllerName + ".log &"; + String shellFile = "./" + strObjControllerName + STR_SHELL_FILE_EXT; + createWrapperShellScript(strJavaCommand, shellFile); + // Send the file to the compute node + String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_RUNTIME_DIR; + runCommand(strCmdSend); + System.out.println("IoTMaster: Sending main controller shell file: " + strCmdSend); + return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile; + } + + + /** + * Construct command line for C++ IoTSlave + * + * @return String + */ + private String getCmdCppIoTSlave(String strObjControllerName) { + + return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + + STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " + + commHan.getComPort(strObjControllerName) + " " + strObjControllerName; + } + + + /** + * sendInteger() sends an integer in bytes + */ + public void sendInteger(int intSend, OutputStream outStream) throws IOException { + + BufferedOutputStream output = (BufferedOutputStream) outStream; + // Transform integer into bytes + ByteBuffer bb = ByteBuffer.allocate(INT_SIZE); + bb.putInt(intSend); + // Send the byte array + output.write(bb.array(), 0, INT_SIZE); + output.flush(); + } + + + /** + * recvInteger() receives integer in bytes + */ + public int recvInteger(InputStream inStream) throws IOException { + + BufferedInputStream input = (BufferedInputStream) inStream; + // Wait until input is available + while(input.available() == 0); + // Read integer - 4 bytes + byte[] recvInt = new byte[INT_SIZE]; + input.read(recvInt, 0, INT_SIZE); + int retVal = ByteBuffer.wrap(recvInt).getInt(); + + return retVal; + } + + + /** + * recvString() receives String in bytes + */ + public String recvString(InputStream inStream) throws IOException { + + BufferedInputStream input = (BufferedInputStream) inStream; + int strLen = recvInteger(inStream); + // Wait until input is available + while(input.available() == 0); + // Read String per strLen + byte[] recvStr = new byte[strLen]; + input.read(recvStr, 0, strLen); + String retVal = new String(recvStr); + + return retVal; + } + + + /** + * sendString() sends a String in bytes + */ + public void sendString(String strSend, OutputStream outStream) throws IOException { + + BufferedOutputStream output = (BufferedOutputStream) outStream; + // Transform String into bytes + byte[] strSendBytes = strSend.getBytes(); + int strLen = strSend.length(); + // Send the string length first + sendInteger(strLen, outStream); + // Send the byte array + output.write(strSendBytes, 0, strLen); + output.flush(); + } + + + /** + * Convert integer to enum + */ + public IoTCommCode getCode(int intCode) throws IOException { + + IoTCommCode[] commCode = IoTCommCode.values(); + IoTCommCode retCode = commCode[intCode]; + return retCode; + + } + + + /** + * Receive ACK + */ + public synchronized boolean recvAck(InputStream inStream) throws IOException { + + int intAck = recvInteger(inStream); + IoTCommCode codeAck = getCode(intAck); + if (codeAck == IoTCommCode.ACKNOWLEDGED) + return true; + return false; + + } + + + /** + * Send END + */ + public void sendEndTransfer(OutputStream outStream) throws IOException { + + int endCode = IoTCommCode.END_TRANSFER.ordinal(); + sendInteger(endCode, outStream); + } + + + /** + * Send communication code to C++ + */ + public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException { + + + IoTCommCode commCode = inpCommCode; + int intCode = commCode.ordinal(); + // TODO: delete this later + System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode); + sendInteger(intCode, outStream); recvAck(inStream); + } + + + /** + * Create a main controller object for C++ + */ + public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream); + String strMainObjName = strObjControllerName; + sendString(strMainObjName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE); + } + + + /** + * A helper function that converts Class into String + * + * @param strDataType String MySQL data type + * @return Class + */ + public String getClassConverted(Class cls) { + + if (cls == String.class) { + return "string"; + } else if (cls == int.class) { + return "int"; + } else { + return null; + } + } + + + /** + * A helper function that converts Object into String for transfer to C++ slave + * + * @param obj Object to be converted + * @param strClassType String Java Class type + * @return Object + */ + public String getObjectConverted(Object obj) { + + if (obj instanceof String) { + return (String) obj; + } else if (obj instanceof Integer) { + return Integer.toString((Integer) obj); + } else { + return null; + } + } + + + /** + * Create a driver object for C++ + */ + public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd, + Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses, + OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream); + RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE); + RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE); + sendString(strObjName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE); + sendString(strObjClassName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE); + sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE); + sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE); + sendInteger(iRMIRegistryPort, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE); + sendInteger(iRMIStubPort, outStream); recvAck(inStream); + int numOfArgs = arrFieldValues.length; + RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE); + sendInteger(numOfArgs, outStream); recvAck(inStream); + for(Object obj : arrFieldValues) { + String str = getObjectConverted(obj); + sendString(str, outStream); recvAck(inStream); + } + RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE); + for(Class cls : arrFieldClasses) { + String str = getClassConverted(cls); + sendString(str, outStream); recvAck(inStream); + } + } + + + /** + * Create new IoTSet for C++ + */ + public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream); + RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE); + RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE); + sendString(strObjFieldName, outStream); recvAck(inStream); + } + + + /** + * Create new IoTRelation for C++ + */ + public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream); + RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE); + RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE); + sendString(strObjFieldName, outStream); recvAck(inStream); + } + + + /** + * Get a IoTDeviceAddress object for C++ + */ + public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream, + String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException { + + sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream); + RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE); + sendString(strDeviceAddress, outStream); recvAck(inStream); + sendInteger(iSourcePort, outStream); recvAck(inStream); + sendInteger(iDestPort, outStream); recvAck(inStream); + int iSourceWildCard = (bSourceWildCard ? 1 : 0); + sendInteger(iSourceWildCard, outStream); recvAck(inStream); + int iDestWildCard = (bDestWildCard ? 1 : 0); + sendInteger(iDestWildCard, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE); + } + + + /** + * Get a IoTSet content object for C++ + */ + public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName, + String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort, + OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(iotCommCode, outStream, inStream); + RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE); + // Send info + RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE); + sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE); + sendString(strObjectName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE); + sendString(strObjectClassName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE); + sendString(strObjectClassInterfaceName, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE); + sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE); + sendInteger(iRMIRegistryPort, outStream); recvAck(inStream); + RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE); + sendInteger(iRMIStubPort, outStream); recvAck(inStream); + } + + + /** + * Reinitialize IoTRelation field for C++ + */ + private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException { + + RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE); + sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream); + RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE); + } + + + /** + * Reinitialize IoTSet field for C++ + */ + private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException { + + RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE); + sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream); + RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE); + } + + + /** + * Create driver object for C++ + */ + private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream); + RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE); + } + + + /** + * Invoke init() for C++ + */ + private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException { + + sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream); + RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE); + } + + + /** + * End session for C++ + */ + public void endSessionCpp(OutputStream outStream) throws IOException { + + // Send message to end session + IoTCommCode endSessionCode = IoTCommCode.END_SESSION; + int intCode = endSessionCode.ordinal(); + sendInteger(intCode, outStream); + //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE); + RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE); + } + /** * A method to assign objects to multiple JVMs, including @@ -1132,23 +2004,35 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName)); routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd, strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName)); - + // Read config file + String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT; + STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE); + if(STR_LANGUAGE_CONTROLLER == null) + throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg); // Construct ssh command line and create a controller thread for e.g. AcmeProximity - String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveControllerHostAdd + " cd " + - STR_RUNTIME_DIR + " sudo java " + STR_CLS_PATH + " " + - STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " + - commHan.getComPort(strObjControllerName) + " " + - commHan.getRMIRegPort(strObjControllerName) + " " + - commHan.getRMIStubPort(strObjControllerName) + " >& " + - STR_LOG_FILE_PATH + strObjControllerName + ".log &"; + String strSSHCommand = null; + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) + strSSHCommand = getCmdJavaIoTSlave(strObjControllerName); + else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP)) + strSSHCommand = getCmdCppIoTSlave(strObjControllerName); + else + throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER); RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE); createThread(strSSHCommand); // Wait for connection // Create a new socket for communication ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName)); Socket socket = serverSocket.accept(); - ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream()); - ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream()); + InputStream inStream = null; + OutputStream outStream = null; + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) { + inStream = new ObjectInputStream(socket.getInputStream()); + outStream = new ObjectOutputStream(socket.getOutputStream()); + } else { // At this point the language is certainly C++, otherwise would've complained above + inStream = new BufferedInputStream(socket.getInputStream()); + outStream = new BufferedOutputStream(socket.getOutputStream()); + recvAck(inStream); + } RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE); // PROFILING @@ -1162,37 +2046,23 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT; String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" + strControllerClassName; - // Send .jar file - String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT; - String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" + - strControllerJarName; - File file = new File(strControllerJarNamePath); - commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()), - "Sending file!", inStream, outStream); - // Send file - Class file for object creation - sendFile(serverSocket.accept(), strControllerJarNamePath, file.length()); - Message msgReply = (Message) inStream.readObject(); - RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); - // Send .zip file if additional zip file is specified - String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT; - String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile; - String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG); - if (strAdditionalFile.equals(STR_YES)) { - String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT; - String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" + - strControllerCmpName; - file = new File(strControllerCmpNamePath); - commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()), - "Sending file!", inStream, outStream); - // Send file - Class file for object creation - sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length()); - msgReply = (Message) inStream.readObject(); - RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE); - } - // Create main controller/device object - commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName), - "Create main object!", inStream, outStream); + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) { + sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream); + // Create main controller/device object + commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName), + "Create main object!", inStream, outStream); + } else { + String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT; + String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/"; + sendFileToCppSlave(strControllerFilePath, strControllerZipFile); + createMainObjectCpp(strObjControllerName, outStream, inStream); + } + // Write basic MAC policies for controller + //String strFileName = STR_MAC_POL_PATH + strObjControllerName + STR_MAC_POLICY_EXT; + String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT; + processJailConfig.configureProcessJailControllerPolicies(strObjControllerName, strFileName, + strIoTMasterHostAdd, commHan.getComPort(strObjControllerName)); // PROFILING result = System.currentTimeMillis()-start; System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result); @@ -1204,15 +2074,23 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa // Instrumenting one file RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE); RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE); - FileInputStream fis = new FileInputStream(strControllerClassNamePath); - ClassReader cr = new ClassReader(fis); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE); - cr.accept(crim, 0); - fis.close(); + HashMap hmControllerFieldObjects = null; + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) { + FileInputStream fis = new FileInputStream(strControllerClassNamePath); + ClassReader cr = new ClassReader(fis); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE); + cr.accept(crim, 0); + fis.close(); + hmControllerFieldObjects = crim.getFieldObjects(); + } else { + String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT; + CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE); + hmControllerFieldObjects = crim.getFieldObjects(); + } // Get the object and the class names // Build objects for IoTSet and IoTRelation fields in the controller/device classes - HashMap hmControllerFieldObjects = crim.getFieldObjects(); + //HashMap hmControllerFieldObjects = crim.getFieldObjects(); for(Map.Entry map : hmControllerFieldObjects.entrySet()) { RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE); // Iterate over HashMap and choose between processing @@ -1231,16 +2109,21 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa throw new Error(strErrMsg); } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { // Instrument the IoTAddress - setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd); - instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream); + setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd, strObjControllerName); + instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER); } else { // Any other cases - instrumentIoTSet(map, strFieldName); + instrumentIoTSet(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER); } } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) { - instrumentIoTRelation(map, strFieldName); + instrumentIoTRelation(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER); } } + // Combine controller MAC policies with the main policy file for the host + String strTempFileName = "./" + strObjControllerName + STR_MAC_POLICY_EXT; + processJailConfig.combineControllerMACPolicies(strIoTSlaveControllerHostAdd, strObjControllerName, strTempFileName); + processJailConfig.close(); + // PROFILING result = System.currentTimeMillis()-start; System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n"); @@ -1274,7 +2157,7 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa start = System.currentTimeMillis(); // Separating object creations and Set/Relation initializations - createControllerObjects(); + createDriverObjects(); // PROFILING result = System.currentTimeMillis()-start; @@ -1283,23 +2166,34 @@ String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassNa start = System.currentTimeMillis(); // Sets and relations initializations - initializeSetsAndRelations(inStream, outStream); + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) + initializeSetsAndRelationsJava(inStream, outStream); + else + initializeSetsAndRelationsCpp(inStream, outStream);; // PROFILING result = System.currentTimeMillis()-start; System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n"); - // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD - commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), - "Invoke init() method!", inStream, outStream); + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) + // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD + commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream); + else + invokeInitMethodCpp(outStream, inStream); // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS - outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION)); + if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) { + ObjectOutputStream oStream = (ObjectOutputStream) outStream; + oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION)); + } else // C++ side will wait until the program finishes, it's not generating a separate thread for now + //endSessionCpp(outStream); outStream.close(); inStream.close(); socket.close(); serverSocket.close(); commHan.printLists(); lbIoT.printHostInfo(); + // TODO: Uncomment this - just for experiments! + createMACPolicyThreads(setAddresses); } } catch (IOException |