+ /**
+ * 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<String> setHostAddresses) throws IOException {
+
+ // Create a list of threads
+ List<Thread> threads = new ArrayList<Thread>();
+ // 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);
+ }
+