1 package iotruntime.master;
4 import iotruntime.slave.IoTAddress;
5 import iotruntime.slave.IoTDeviceAddress;
6 import iotruntime.messages.*;
9 import org.objectweb.asm.ClassReader;
10 import org.objectweb.asm.ClassWriter;
11 import org.objectweb.asm.ClassVisitor;
16 import java.io.BufferedReader;
17 import java.io.InputStream;
18 import java.io.InputStreamReader;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.OutputStream;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.IOException;
26 import java.lang.ClassNotFoundException;
27 import java.lang.Class;
28 import java.lang.reflect.*;
29 import java.net.Socket;
30 import java.net.ServerSocket;
31 import java.nio.ByteBuffer;
33 import static java.lang.Math.toIntExact;
35 /** Class IoTMaster is responsible to use ClassRuntimeInstrumenterMaster
36 * to instrument the controller/device bytecode and starts multiple
37 * IoTSlave running on different JVM's in a distributed fashion.
39 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
43 public final class IoTMaster {
46 * IoTMaster class properties
48 * CommunicationHandler maintains the data structure for hostnames and ports
49 * LoadBalancer assigns a job onto a host based on certain metrics
51 private CommunicationHandler commHan;
52 private LoadBalancer lbIoT;
53 private RouterConfig routerConfig;
54 private ProcessJailConfig processJailConfig;
55 private ObjectInitHandler objInitHand;
56 private ObjectAddressInitHandler objAddInitHand;
57 private String[] strObjectNames;
58 // Now this can be either ClassRuntimeInstrumenterMaster or CRuntimeInstrumenterMaster
59 private Map<String,Object> mapClassNameToCrim;
62 * These properties hold information of a certain object
65 private String strObjName;
66 private String strObjClassName;
67 private String strObjClassInterfaceName;
68 private String strObjStubClsIntfaceName;
69 private String strIoTMasterHostAdd;
70 private String strIoTSlaveControllerHostAdd;
71 private String strIoTSlaveObjectHostAdd;
72 private Class[] arrFieldClasses;
73 private Object[] arrFieldValues;
74 private Socket filesocket;
77 * For connection with C++ IoTSlave
79 private ServerSocket serverSocketCpp;
80 private Socket socketCpp;
81 private BufferedInputStream inputCpp;
82 private BufferedOutputStream outputCpp;
84 // Constants that are to be extracted from config file
85 private static String STR_MASTER_MAC_ADD;
86 private static String STR_IOT_CODE_PATH;
87 private static String STR_CONT_PATH;
88 private static String STR_RUNTIME_DIR;
89 private static String STR_SLAVE_DIR;
90 private static String STR_CLS_PATH;
91 private static String STR_RMI_PATH;
92 private static String STR_RMI_HOSTNAME;
93 private static String STR_LOG_FILE_PATH;
94 private static String STR_USERNAME;
95 private static String STR_ROUTER_ADD;
96 private static String STR_MONITORING_HOST;
97 private static String STR_ZB_GATEWAY_ADDRESS;
98 private static String STR_ZB_GATEWAY_PORT;
99 private static String STR_ZB_IOTMASTER_PORT;
100 private static String STR_JVM_INIT_HEAP_SIZE;
101 private static String STR_JVM_MAX_HEAP_SIZE;
102 private static String STR_LANGUAGE_CONTROLLER;
103 private static String STR_SKEL_CLASS_SUFFIX;
104 private static String STR_STUB_CLASS_SUFFIX;
105 private static String STR_ACTIVATE_SANDBOXING;
106 private static String STR_POLICY_ON;
107 private static String STR_MAC_TO_IP_TRANSLATION;
108 private static boolean BOOL_VERBOSE;
111 * IoTMaster class constants
113 * Name constants - not to be configured by users
115 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
116 private static final String STR_CFG_FILE_EXT = ".config";
117 private static final String STR_CLS_FILE_EXT = ".class";
118 private static final String STR_JAR_FILE_EXT = ".jar";
119 private static final String STR_MAC_POLICY_EXT = ".tomoyo.pol";
120 private static final String STR_SHELL_FILE_EXT = ".sh";
121 private static final String STR_SO_FILE_EXT = ".so";
122 private static final String STR_ZIP_FILE_EXT = ".zip";
123 private static final String STR_TCP_PROTOCOL = "tcp";
124 private static final String STR_UDP_PROTOCOL = "udp";
125 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
126 private static final String STR_NO_PROTOCOL = "nopro";
127 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
128 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
129 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
130 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
131 private static final String STR_LANGUAGE = "LANGUAGE";
132 private static final String STR_ADD_MAC_POL = "ADDITIONAL_MAC_POLICY";
133 private static final String STR_YES = "Yes";
134 private static final String STR_NO = "No";
135 private static final String STR_JAVA = "Java";
136 private static final String STR_CPP = "C++";
137 private static final String STR_SSH = "ssh";
138 private static final String STR_SCP = "scp";
139 private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
140 private static final String STR_SHELL_HEADER = "#!/bin/sh";
141 private static final String STR_JAVA_PATH = "/usr/bin/java";
142 private static final String STR_MAC_POL_PATH = "tomoyo/";
143 private static final String STR_TMP = "tmp";
144 private static final String STR_ARP = "arp";
146 private static int INT_SIZE = 4; // send length in the size of integer (4 bytes)
147 private static final int INT_DNS_PORT = 53;
150 * Runtime class name constants - not to be configured by users
152 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
153 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
154 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
155 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
156 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
157 private static final String STR_IOT_ADD_CLS = "IoTAddress";
163 public IoTMaster(String[] argObjNms) {
168 processJailConfig = null;
170 objAddInitHand = null;
171 strObjectNames = argObjNms;
173 strObjClassName = null;
174 strObjClassInterfaceName = null;
175 strObjStubClsIntfaceName = null;
176 strIoTMasterHostAdd = null;
177 strIoTSlaveControllerHostAdd = null;
178 strIoTSlaveObjectHostAdd = null;
179 arrFieldClasses = null;
180 arrFieldValues = null;
182 mapClassNameToCrim = null;
183 // Connection with C++ IoTSlave
184 serverSocketCpp = null;
189 STR_MASTER_MAC_ADD = null;
190 STR_IOT_CODE_PATH = null;
191 STR_CONT_PATH = null;
192 STR_RUNTIME_DIR = null;
193 STR_SLAVE_DIR = null;
196 STR_RMI_HOSTNAME = null;
197 STR_LOG_FILE_PATH = null;
199 STR_ROUTER_ADD = null;
200 STR_MONITORING_HOST = null;
201 STR_ZB_GATEWAY_ADDRESS = null;
202 STR_ZB_GATEWAY_PORT = null;
203 STR_ZB_IOTMASTER_PORT = null;
204 STR_JVM_INIT_HEAP_SIZE = null;
205 STR_JVM_MAX_HEAP_SIZE = null;
206 STR_LANGUAGE_CONTROLLER = null;
207 STR_ACTIVATE_SANDBOXING = null;
208 STR_POLICY_ON = null;
209 STR_MAC_TO_IP_TRANSLATION = null;
210 BOOL_VERBOSE = false;
214 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
218 private void initLiveDataStructure() {
220 commHan = new CommunicationHandler(BOOL_VERBOSE);
221 lbIoT = new LoadBalancer(BOOL_VERBOSE);
222 lbIoT.setupLoadBalancer();
223 routerConfig = new RouterConfig();
224 // Get MAC to IP translation either from /tmp/dhcp.leases or arp command
225 if (STR_MAC_TO_IP_TRANSLATION.equals(STR_TMP))
226 routerConfig.getAddressListTmp(STR_ROUTER_ADD);
227 else if (STR_MAC_TO_IP_TRANSLATION.equals(STR_ARP))
228 routerConfig.getAddressListArp(STR_ROUTER_ADD);
230 throw new Error("IoTMaster: Unknown value for STR_MAC_TO_IP_TRANSLATION: " + STR_MAC_TO_IP_TRANSLATION);
231 processJailConfig = new ProcessJailConfig();
232 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
233 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
234 mapClassNameToCrim = new HashMap<String,Object>();
238 * getPrintWriter() gets a new PrintWriter for a new object
240 * @param strObjectName String object name
241 * @return PrintWriter
243 private PrintWriter getPrintWriter(String strObjectName) {
245 FileWriter fw = null;
247 fw = new FileWriter(strObjectName);
248 } catch (IOException ex) {
249 ex.printStackTrace();
251 PrintWriter printWriter = new PrintWriter(new BufferedWriter(fw));
256 * A method to initialize constants from config file
260 private void parseIoTMasterConfigFile() {
261 // Parse configuration file
262 Properties prop = new Properties();
263 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
264 File file = new File(strCfgFileName);
265 FileInputStream fis = null;
267 fis = new FileInputStream(file);
270 } catch (IOException ex) {
271 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
272 ex.printStackTrace();
274 // Initialize constants from config file
275 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
276 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
277 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
278 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
279 STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR");
280 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
281 STR_RMI_PATH = prop.getProperty("RMI_PATH");
282 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
283 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
284 STR_USERNAME = prop.getProperty("USERNAME");
285 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
286 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
287 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
288 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
289 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
290 STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
291 STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
292 STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
293 STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
294 STR_ACTIVATE_SANDBOXING = prop.getProperty("ACTIVATE_SANDBOXING");
295 STR_POLICY_ON = prop.getProperty("POLICY_ON");
296 STR_MAC_TO_IP_TRANSLATION = prop.getProperty("MAC_TO_IP_TRANSLATION");
297 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
301 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
302 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
303 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
304 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
305 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
306 RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE);
307 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
308 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
309 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
310 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
311 RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE);
312 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
313 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
314 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
315 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
316 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
317 RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
318 RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
319 RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
320 RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
321 RuntimeOutput.print("STR_ACTIVATE_SANDBOXING=" + STR_ACTIVATE_SANDBOXING, BOOL_VERBOSE);
322 RuntimeOutput.print("STR_POLICY_ON=" + STR_POLICY_ON, BOOL_VERBOSE);
323 RuntimeOutput.print("STR_MAC_TO_IP_TRANSLATION=" + STR_MAC_TO_IP_TRANSLATION, BOOL_VERBOSE);
324 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
325 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
329 * A method to parse information from a config file
331 * @param strCfgFileName Config file name
332 * @param strCfgField Config file field name
335 private String parseConfigFile(String strCfgFileName, String strCfgField) {
336 // Parse configuration file
337 Properties prop = new Properties();
338 File file = new File(strCfgFileName);
339 FileInputStream fis = null;
341 fis = new FileInputStream(file);
344 } catch (IOException ex) {
345 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
346 ex.printStackTrace();
348 RuntimeOutput.print("IoTMaster: Reading " + strCfgField +
349 " from config file: " + strCfgFileName + " with value: " +
350 prop.getProperty(strCfgField, null), BOOL_VERBOSE);
351 // NULL is returned if the property isn't found
352 return prop.getProperty(strCfgField, null);
356 * A method to send files from IoTMaster
358 * @param filesocket File socket object
359 * @param sFileName File name
360 * @param lFLength File length
363 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
365 File file = new File(sFileName);
366 byte[] bytFile = new byte[toIntExact(lFLength)];
367 InputStream inFileStream = new FileInputStream(file);
369 OutputStream outFileStream = filesocket.getOutputStream();
371 while ((iCount = inFileStream.read(bytFile)) > 0) {
372 outFileStream.write(bytFile, 0, iCount);
375 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
379 * A method to create a thread
381 * @param sSSHCmd SSH command
384 private void createThread(String sSSHCmd) throws IOException {
386 // Start a new thread to start a new JVM
388 Runtime runtime = Runtime.getRuntime();
389 Process process = runtime.exec(sSSHCmd);
391 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
395 * A method to send command from master and receive reply from slave
397 * @params msgSend Message object
398 * @params strPurpose String that prints purpose message
399 * @params inStream Input stream
400 * @params outStream Output stream
403 private void commMasterToSlave(Message msgSend, String strPurpose,
404 InputStream _inStream, OutputStream _outStream)
405 throws IOException, ClassNotFoundException {
407 // Send message/command from master
408 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
409 outStream.writeObject(msgSend);
410 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
412 // Get reply from slave as acknowledgment
413 ObjectInputStream inStream = (ObjectInputStream) _inStream;
414 Message msgReply = (Message) inStream.readObject();
415 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
419 * A private method to instrument IoTSet device
421 * @params strFieldIdentifier String field name + object ID
422 * @params strFieldName String field name
423 * @params strIoTSlaveObjectHostAdd String slave host address
424 * @params inStream ObjectInputStream communication
425 * @params outStream ObjectOutputStream communication
426 * @params strLanguage String language
429 private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
430 InputStream inStream, OutputStream outStream, String strLanguage)
431 throws IOException, ClassNotFoundException, InterruptedException {
433 // Get information from the set
434 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
435 RuntimeOutput.print("IoTMaster: DEBUG: Getting into instrumentIoTSetDevice!", BOOL_VERBOSE);
436 // Create a new IoTSet
437 if(strLanguage.equals(STR_JAVA)) {
438 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
439 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
441 createNewIoTSetCpp(strFieldName, outStream, inStream);
442 int iRows = listObject.size();
443 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
444 // Transfer the address
445 for(int iRow=0; iRow<iRows; iRow++) {
446 arrFieldValues = listObject.get(iRow);
447 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
448 String strDeviceAddress = null;
449 String strDeviceAddressKey = null;
450 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
451 strDeviceAddress = strIoTSlaveObjectHostAdd;
452 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
454 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
455 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
457 int iDestDeviceDriverPort = (int) arrFieldValues[1];
458 String strProtocol = (String) arrFieldValues[2];
459 // Check for wildcard feature
460 boolean bSrcPortWildCard = false;
461 boolean bDstPortWildCard = false;
462 if (arrFieldValues.length > 3) {
463 bSrcPortWildCard = (boolean) arrFieldValues[3];
464 bDstPortWildCard = (boolean) arrFieldValues[4];
466 // Add the port connection into communication handler - if it's not assigned yet
467 if (commHan.getComPort(strDeviceAddressKey) == null) {
468 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
470 // Send address one by one
471 if(strLanguage.equals(STR_JAVA)) {
472 Message msgGetIoTSetObj = null;
473 if (bDstPortWildCard) {
474 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
475 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
476 strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
478 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
479 strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
480 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
482 getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort,
483 bSrcPortWildCard, bDstPortWildCard);
485 // Reinitialize IoTSet on device object
486 if(strLanguage.equals(STR_JAVA))
487 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
489 reinitializeIoTSetFieldCpp(outStream, inStream);
494 * A private method to instrument IoTSet Zigbee device
496 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
497 * @params strFieldName String field name
498 * @params strIoTSlaveObjectHostAdd String slave host address
499 * @params inStream ObjectInputStream communication
500 * @params inStream ObjectOutputStream communication
501 * @params strLanguage String language
504 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
505 InputStream inStream, OutputStream outStream, String strLanguage)
506 throws IOException, ClassNotFoundException, InterruptedException {
508 // Get information from the set
509 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
510 // Create a new IoTSet
511 if(strLanguage.equals(STR_JAVA)) {
512 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
513 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
514 } else // TODO: will need to implement IoTSet Zigbee for C++ later
516 // Prepare ZigbeeConfig
517 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
518 String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress;
519 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
520 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
521 commHan.addDevicePort(iZigbeeIoTMasterPort);
522 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
524 // Add the port connection into communication handler - if it's not assigned yet
525 if (commHan.getComPort(strZigbeeGWAddressKey) == null) {
526 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey);
528 int iRows = setInstrumenter.numberOfRows();
529 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
530 // Transfer the address
531 for(int iRow=0; iRow<iRows; iRow++) {
532 arrFieldValues = setInstrumenter.fieldValues(iRow);
533 // Get device address
534 String strZBDevAddress = (String) arrFieldValues[0];
535 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
536 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
537 // Send address one by one
538 if(strLanguage.equals(STR_JAVA)) {
539 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
540 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
541 } else // TODO: Implement IoTSet Zigbee for C++
544 zbConfig.closeConnection();
545 // Reinitialize IoTSet on device object
546 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
551 * A private method to instrument IoTSet of addresses
553 * @params strFieldIdentifier String field name + object ID
554 * @params strFieldName String field name
555 * @params inStream ObjectInputStream communication
556 * @params inStream ObjectOutputStream communication
557 * @params strLanguage String language
560 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
561 InputStream inStream, OutputStream outStream, String strLanguage)
562 throws IOException, ClassNotFoundException, InterruptedException {
564 // Get information from the set
565 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
566 // Create a new IoTSet
567 if(strLanguage.equals(STR_JAVA)) {
568 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
569 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
572 int iRows = listObject.size();
573 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
574 // Transfer the address
575 for(int iRow=0; iRow<iRows; iRow++) {
576 arrFieldValues = listObject.get(iRow);
577 // Get device address
578 String strAddress = (String) arrFieldValues[0];
579 // Send address one by one
580 if(strLanguage.equals(STR_JAVA)) {
581 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
582 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
583 } else // TODO: Implement IoTSet Address for C++
586 // Reinitialize IoTSet on device object
587 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
588 "Reinitialize IoTSet fields!", inStream, outStream);
593 * A private method to instrument an object on a specific machine and setting up policies
595 * @params strFieldObjectID String field object ID
596 * @params strObjControllerName String object controller name
597 * @params strLanguage String language
600 private void instrumentObject(String strFieldObjectID, String strObjControllerName, String strLanguage) throws IOException {
602 // Extract the interface name for RMI
603 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
604 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
605 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
606 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
607 // Create an object name, e.g. ProximitySensorImplPS1
608 strObjName = strObjClassName + strFieldObjectID;
609 // Check first if host exists
610 if(commHan.objectExists(strObjName)) {
611 // If this object exists already ...
612 // Re-read IoTSlave object hostname for further reference
613 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
614 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
616 // If this is a new object ... then create one
617 // Get host address for IoTSlave from LoadBalancer
618 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
619 if (strIoTSlaveControllerHostAdd == null)
620 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
621 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
622 // Add port connection and get port numbers
623 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
624 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
625 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
626 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
627 // ROUTING POLICY: IoTMaster and device/controller object
628 // Master-slave communication
629 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
630 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
631 // ROUTING POLICY: Send the same routing policy to both the hosts
632 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
633 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
634 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
635 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
636 // Need to accommodate callback functions here - open ports for TCP
637 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
638 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
639 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
640 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
641 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
642 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
643 // Configure MAC policies for objects
644 String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT;
645 if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
646 processJailConfig.configureProcessJailDeviceDriverPolicies(strIoTSlaveObjectHostAdd, strObjName, strObjClassName,
647 strFileName, strIoTMasterHostAdd, commHan.getComPort(strObjName), commHan.getRMIRegPort(strObjName),
648 commHan.getRMIStubPort(strObjName));
649 // Check for additional MAC policy
650 String strMACConfigPath = STR_IOT_CODE_PATH + strObjClassName + "/";
651 String strCfgFile = strMACConfigPath + strObjClassName + STR_CFG_FILE_EXT;
652 String strAddMACPolicy = parseConfigFile(strCfgFile, STR_ADD_MAC_POL);
653 if (strAddMACPolicy != null && strAddMACPolicy.equals("Yes"))
654 processJailConfig.combineAdditionalMACPolicy(strMACConfigPath, strObjClassName, strIoTSlaveObjectHostAdd);
655 processJailConfig.configureProcessJailContRMIPolicies(strObjControllerName, strIoTSlaveObjectHostAdd,
656 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
658 // Instrument the IoTSet declarations inside the class file
659 instrumentObjectIoTSet(strFieldObjectID, strLanguage);
661 // Send routing policy to router for controller object
662 // ROUTING POLICY: RMI communication - RMI registry and stub ports
663 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
664 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
665 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
666 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
667 // Send the same set of routing policies to compute nodes
668 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
669 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
670 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
671 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
672 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
673 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
674 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
675 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
680 * A private method to set router policies for IoTDeviceAddress objects
682 * @params strFieldIdentifier String field name + object ID
683 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
684 * @params strIoTSlaveObjectHostAdd String slave host address
687 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
688 String strIoTSlaveObjectHostAdd) {
690 // Get information from the set
691 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
692 int iRows = setInstrumenter.numberOfRows();
693 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
694 // Transfer the address
695 for(int iRow=0; iRow<iRows; iRow++) {
696 arrFieldValues = setInstrumenter.fieldValues(iRow);
697 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
698 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
699 String strDeviceAddress = null;
700 String strDeviceAddressKey = null;
701 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
702 strDeviceAddress = strIoTSlaveObjectHostAdd;
703 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
704 } else { // Concatenate object name and IP address to give unique key - for a case where there is one device for multiple drivers
705 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
706 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
708 int iDestDeviceDriverPort = (int) arrFieldValues[1];
709 String strProtocol = (String) arrFieldValues[2];
710 // Add the port connection into communication handler - if it's not assigned yet
711 if (commHan.getComPort(strDeviceAddressKey) == null)
712 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
713 boolean bDstPortWildCard = false;
714 // Recognize this and allocate different ports for it
715 if (arrFieldValues.length > 3) {
716 bDstPortWildCard = (boolean) arrFieldValues[4];
717 if (bDstPortWildCard) { // This needs a unique source port
718 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
719 commHan.addAdditionalPort(strUniqueDev);
722 // Send routing policy to router for device drivers and devices
723 // ROUTING POLICY: RMI communication - RMI registry and stub ports
724 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
725 // Port number -1 means that we don't set the policy strictly to port number level
726 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
727 // ROUTING POLICY: Device driver and device
728 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
729 // ROUTING POLICY: Send to the compute node where the device driver is
730 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
731 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
732 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
733 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
734 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
735 // This is a TCP protocol that connects, e.g. a phone to our runtime system
736 // that provides a gateway access (accessed through destination port number)
737 commHan.addDevicePort(iDestDeviceDriverPort);
738 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
739 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
740 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
741 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
742 // Configure MAC policies
743 if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
744 processJailConfig.configureProcessJailGWDevicePolicies(strIoTSlaveObjectHostAdd, STR_ROUTER_ADD, strDeviceAddress, INT_DNS_PORT);
746 // Other port numbers...
747 commHan.addDevicePort(iDestDeviceDriverPort);
748 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
749 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
750 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
751 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
752 // Configure MAC policies
753 if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
754 processJailConfig.configureProcessJailDevicePolicies(strIoTSlaveObjectHostAdd, strProtocol,
755 commHan.getComPort(strDeviceAddressKey), strDeviceAddress, iDestDeviceDriverPort);
761 * A private method to set router policies for IoTAddress objects
763 * @params strFieldIdentifier String field name + object ID
764 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
765 * @params strHostAddress String host address
768 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
769 String strHostAddress, String strControllerName) {
771 // Get information from the set
772 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
773 int iRows = setInstrumenter.numberOfRows();
774 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
775 // Transfer the address
776 for(int iRow=0; iRow<iRows; iRow++) {
777 arrFieldValues = setInstrumenter.fieldValues(iRow);
778 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
779 // Get device address
780 String strAddress = (String) arrFieldValues[0];
781 // Setting up router policies for HTTP/HTTPs
782 if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
783 if (strControllerName != null) {
784 processJailConfig.configureProcessJailInetAddressPolicies(strControllerName, STR_ROUTER_ADD, strAddress);
786 processJailConfig.configureProcessJailInetAddressPolicies(strHostAddress, STR_ROUTER_ADD, strAddress);
789 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
790 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
795 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
797 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
799 * @params strFieldObjectID String field object ID
800 * @params strLanguage String language
803 private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
805 // If this is a new object ... then create one
806 // Instrument the class source code and look for IoTSet for device addresses
807 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
808 HashMap<String,Object> hmObjectFieldObjects = null;
809 if(strLanguage.equals(STR_JAVA)) {
810 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
811 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
812 ClassReader cr = new ClassReader(fis);
813 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
814 // We need Object ID to instrument IoTDeviceAddress
815 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
818 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
819 hmObjectFieldObjects = crim.getFieldObjects();
821 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
822 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE);
823 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
824 hmObjectFieldObjects = crim.getFieldObjects();
826 // Get the object and the class names
827 // Build objects for IoTSet and IoTRelation fields in the device object classes
828 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
829 strFieldObjectID, BOOL_VERBOSE);
830 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
831 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
832 // Iterate over HashMap and choose between processing
833 String strFieldName = map.getKey();
834 String strClassName = map.getValue().getClass().getName();
835 String strFieldIdentifier = strFieldName + strFieldObjectID;
836 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
837 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
838 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
839 // Instrument the normal IoTDeviceAddress
840 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
841 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
842 // Instrument the IoTAddress
843 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd, null);
844 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
845 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
846 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
849 String strErrMsg = "IoTMaster: Device driver object" +
850 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
851 " or IoTSet<IoTZigbeeAddress>!";
852 throw new Error(strErrMsg);
855 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
856 throw new Error(strErrMsg);
863 * A private method to send files to a Java slave driver
865 * @params serverSocket ServerSocket
866 * @params _inStream InputStream
867 * @params _outStream OutputStream
868 * @params strObjName String
869 * @params strObjClassName String
870 * @params strObjClassInterfaceName String
871 * @params strObjStubClsIntfaceName String
872 * @params strIoTSlaveObjectHostAdd String
873 * @params strFieldObjectID String
874 * @params arrFieldValues Object[]
875 * @params arrFieldClasses Class[]
878 private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream,
879 String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
880 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
881 throws IOException, ClassNotFoundException {
883 ObjectInputStream inStream = (ObjectInputStream) _inStream;
884 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
885 // Create message to transfer file first
886 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
887 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
888 File file = new File(sPath);
889 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
890 "Sending file!", inStream, outStream);
891 // Send file - JAR file for object creation
892 sendFile(serverSocket.accept(), sPath, file.length());
893 Message msgReply = (Message) inStream.readObject();
894 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
895 // Pack object information to create object on a IoTSlave
896 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
897 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
898 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
900 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
905 * A private method to send files to a Java slave driver
909 private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd)
910 throws IOException, ClassNotFoundException {
912 // Create message to transfer file first
913 String sFileName = strObjClassName + STR_ZIP_FILE_EXT;
914 String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
915 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR;
916 runCommand(strCmdSend);
917 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
919 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
920 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
921 runCommand(strCmdUnzip);
922 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
928 * Construct command line for Java IoTSlave
932 private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
934 // Create an Shell executable
935 String strJavaCommand = STR_SHELL_HEADER + "\nexec sudo " + STR_JAVA_PATH + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " +
936 STR_RMI_HOSTNAME + strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
937 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
938 commHan.getRMIStubPort(strObjName) + " > " + STR_LOG_FILE_PATH + strObjName + ".log &";
939 String shellFile = "./" + strObjName + STR_SHELL_FILE_EXT;
940 createWrapperShellScript(strJavaCommand, shellFile);
941 // Send the file to the compute node
942 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_RUNTIME_DIR;
943 runCommand(strCmdSend);
944 RuntimeOutput.print("IoTMaster: Sending shell file: " + strCmdSend, BOOL_VERBOSE);
945 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
950 * Construct command line for C++ IoTSlave
954 private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
956 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
957 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
958 commHan.getComPort(strObjName) + " " + strObjName;
963 * createWrapperShellScript() gets a wrapper shell script
965 * @param strCommand String command
966 * @param strObjectName String object name
967 * @return PrintWriter
969 private void createWrapperShellScript(String strCommand, String strFileName) {
971 PrintWriter printWriter = getPrintWriter(strFileName);
972 printWriter.println(strCommand);
974 runCommand("chmod 755 " + strFileName);
979 * A private method to create an object on a specific machine
981 * @params strObjName String object name
982 * @params strObjClassName String object class name
983 * @params strObjClassInterfaceName String object class interface name
984 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
985 * @params strFieldObjectID String field object ID
986 * @params arrFieldValues Array of field values
987 * @params arrFieldClasses Array of field classes
990 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
991 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
992 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
995 String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
996 String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
997 if(strLanguageDriver == null) // Read just the field LANGUAGE if the first read is null
998 strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
999 if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
1000 throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
1001 // Construct ssh command line
1002 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
1003 // java -cp $CLASSPATH:./*.jar
1004 // -Djava.rmi.server.codebase=file:./*.jar
1005 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
1006 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
1007 String strSSHCommand = null;
1008 if(strLanguageDriver.equals(STR_JAVA))
1009 strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
1010 else if(strLanguageDriver.equals(STR_CPP))
1011 strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
1013 throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
1014 RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
1015 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1016 // Start a new thread to start a new JVM
1017 createThread(strSSHCommand);
1018 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
1019 Socket socket = serverSocket.accept();
1020 //InputStream inStream = new ObjectInputStream(socket.getInputStream());
1021 //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
1022 InputStream inStream = null;
1023 OutputStream outStream = null;
1024 if(strLanguageDriver.equals(STR_JAVA)) {
1025 inStream = new ObjectInputStream(socket.getInputStream());
1026 outStream = new ObjectOutputStream(socket.getOutputStream());
1027 } else { // At this point the language is certainly C++, otherwise would've complained above
1028 inStream = new BufferedInputStream(socket.getInputStream());
1029 outStream = new BufferedOutputStream(socket.getOutputStream());
1032 if(strLanguageDriver.equals(STR_JAVA)) {
1033 sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName,
1034 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1035 strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
1037 sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd);
1038 createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd,
1039 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses,
1040 outStream, inStream);
1042 // Instrument the class source code and look for IoTSet for device addresses
1043 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
1044 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE);
1045 // Get the object and the class names
1046 // Build objects for IoTSet and IoTRelation fields in the device object classes
1047 Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
1048 HashMap<String,Object> hmObjectFieldObjects = null;
1049 if (crimObj instanceof ClassRuntimeInstrumenterMaster) {
1050 ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj;
1051 hmObjectFieldObjects = crim.getFieldObjects();
1052 } else if (crimObj instanceof CRuntimeInstrumenterMaster) {
1053 CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj;
1054 hmObjectFieldObjects = crim.getFieldObjects();
1056 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
1057 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1058 // Iterate over HashMap and choose between processing
1059 String strFieldName = map.getKey();
1060 String strClassName = map.getValue().getClass().getName();
1061 String strFieldIdentifier = strFieldName + strFieldObjectID;
1062 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1063 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1064 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1065 // Instrument the normal IoTDeviceAddress
1066 synchronized(this) {
1067 //RuntimeOutput.print("IoTMaster: DEBUG: Processing " + STR_IOT_DEV_ADD_CLS + "!", BOOL_VERBOSE);
1068 instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1070 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1071 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
1072 synchronized(this) {
1073 instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1075 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1076 // Instrument the IoTAddress
1077 synchronized(this) {
1078 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
1081 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
1082 " or IoTSet<IoTZigbeeAddress>!";
1083 throw new Error(strErrMsg);
1086 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
1087 throw new Error(strErrMsg);
1091 // TODO: Change this later
1092 if(strLanguageDriver.equals(STR_JAVA)) {
1093 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
1094 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1095 } else { // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
1096 createDriverObjectCpp(outStream, inStream);
1097 //endSessionCpp(outStream);
1103 serverSocket.close();
1108 * A private method to create controller objects
1112 private void createDriverObjects() throws InterruptedException {
1114 // Create a list of threads
1115 List<Thread> threads = new ArrayList<Thread>();
1116 // Get the list of active controller objects and loop it
1117 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
1118 for(String strObjName : listActiveControllerObject) {
1120 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
1121 Thread objectThread = new Thread(new Runnable() {
1123 synchronized(this) {
1125 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
1126 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
1127 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
1128 commHan.getArrayFieldClasses(strObjName));
1129 } catch (IOException |
1130 ClassNotFoundException |
1131 InterruptedException ex) {
1132 ex.printStackTrace();
1137 threads.add(objectThread);
1138 objectThread.start();
1141 for (Thread thread : threads) {
1144 } catch (InterruptedException ex) {
1145 ex.printStackTrace();
1152 * A private method to instrument IoTSet
1154 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
1155 * @params strFieldName String field name
1156 * @params strLanguage String language
1159 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strObjControllerName, String strLanguage)
1160 throws IOException, ClassNotFoundException, InterruptedException {
1162 // Get information from the set
1163 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1164 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
1166 int iRows = setInstrumenter.numberOfRows();
1167 for(int iRow=0; iRow<iRows; iRow++) {
1168 // Get field classes and values
1169 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
1170 arrFieldValues = setInstrumenter.fieldValues(iRow);
1171 // Get object ID and class name
1172 String strObjID = setInstrumenter.fieldObjectID(iRow);
1173 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
1174 // Call the method to create an object
1175 instrumentObject(strObjID, strObjControllerName, strLanguage);
1176 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1177 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
1178 commHan.getRMIStubPort(strObjName));
1184 * A private method to instrument IoTRelation
1186 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
1187 * @params strFieldName String field name
1188 * @params strLanguage String language
1191 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strObjControllerName, String strLanguage)
1192 throws IOException, ClassNotFoundException, InterruptedException {
1194 // Get information from the set
1195 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
1196 int iRows = relationInstrumenter.numberOfRows();
1197 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
1199 for(int iRow=0; iRow<iRows; iRow++) {
1200 // Operate on the first set first
1201 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
1202 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
1203 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
1204 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
1205 // Call the method to create an object
1206 instrumentObject(strObjID, strObjControllerName, strLanguage);
1207 // Get the first object controller host address
1208 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1209 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1210 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1211 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1212 // Operate on the second set
1213 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
1214 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
1215 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
1216 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
1217 // Call the method to create an object
1218 instrumentObject(strObjID, strObjControllerName, strLanguage);
1219 // Get the second object controller host address
1220 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1221 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1222 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1223 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1224 // ROUTING POLICY: first and second controller objects in IoTRelation
1225 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
1226 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1227 // ROUTING POLICY: Send the same routing policy to both the hosts
1228 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1229 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1230 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1231 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1236 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1238 * @params inStream ObjectInputStream communication
1239 * @params outStream ObjectOutputStream communication
1242 private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream)
1243 throws IOException, ClassNotFoundException {
1244 // Get list of fields
1245 List<String> strFields = objInitHand.getListOfFields();
1246 // Iterate on HostAddress
1247 for(String str : strFields) {
1248 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1249 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1250 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1251 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
1252 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1253 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1254 for (ObjectInitInfo objInitInfo : listObject) {
1255 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1256 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1257 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
1258 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1259 "Get IoTSet object!", inStream, outStream);
1262 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1263 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1264 "Renitialize IoTSet field!", inStream, outStream);
1265 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1266 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1267 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1268 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1269 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1270 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1271 Iterator it = listSecondObject.iterator();
1272 for (ObjectInitInfo objInitInfo : listObject) {
1273 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1274 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
1275 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1276 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1277 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1278 "Get IoTRelation first object!", inStream, outStream);
1279 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1280 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1281 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1282 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1283 objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1284 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()),
1285 "Get IoTRelation second object!", inStream, outStream);
1287 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1288 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1289 "Renitialize IoTRelation field!", inStream, outStream);
1295 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1297 * @params inStream ObjectInputStream communication
1298 * @params outStream ObjectOutputStream communication
1301 private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream)
1302 throws IOException, ClassNotFoundException {
1303 // Get list of fields
1304 List<String> strFields = objInitHand.getListOfFields();
1305 // Iterate on HostAddress
1306 for(String str : strFields) {
1307 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1308 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1309 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1310 createNewIoTSetCpp(str, outStream, inStream);
1311 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1312 for (ObjectInitInfo objInitInfo : listObject) {
1313 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1314 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1315 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1316 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1318 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1319 reinitializeIoTSetFieldCpp(outStream, inStream);
1320 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1321 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1322 createNewIoTRelationCpp(str, outStream, inStream);
1323 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1324 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1325 Iterator it = listSecondObject.iterator();
1326 for (ObjectInitInfo objInitInfo : listObject) {
1327 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1328 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1329 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1330 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1331 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1332 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1333 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(),
1334 objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1335 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream);
1337 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1338 reinitializeIoTRelationFieldCpp(outStream, inStream);
1344 * A method to set router basic policies at once
1346 * @param strRouter String router name
1349 private void setRouterBasicPolicies(String strRouter) {
1351 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1352 routerConfig.initMainPolicy(strRouter);
1353 routerConfig.combineRouterPolicies(strRouter);
1354 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1355 routerConfig.configureRouterDHCPPolicies(strRouter);
1356 routerConfig.configureRouterDNSPolicies(strRouter);
1357 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1358 routerConfig.configureRejectPolicies(strRouter);
1362 * A method to set host basic policies at once
1364 * @param strHost String host name
1367 private void setHostBasicPolicies(String strHost) {
1369 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1370 routerConfig.initMainPolicy(strHost);
1371 routerConfig.combineRouterPolicies(strHost);
1372 routerConfig.configureHostDHCPPolicies(strHost);
1373 routerConfig.configureHostDNSPolicies(strHost);
1374 if (strHost.equals(strMonitorHost)) {
1375 // Check if this is the monitoring host
1376 routerConfig.configureHostICMPPolicies(strHost);
1377 routerConfig.configureHostSSHPolicies(strHost);
1379 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1380 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1382 // Apply SQL allowance policies to master host
1383 if (strHost.equals(strIoTMasterHostAdd)) {
1384 routerConfig.configureHostSQLPolicies(strHost);
1386 routerConfig.configureRejectPolicies(strHost);
1390 * A method to create a thread for policy deployment
1392 * @param strRouterAddress String router address to configure
1393 * @param setHostAddresses Set of strings for host addresses to configure
1396 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1398 // Create a list of threads
1399 List<Thread> threads = new ArrayList<Thread>();
1400 // Start threads for hosts
1401 for(String strAddress : setHostAddresses) {
1402 Thread policyThread = new Thread(new Runnable() {
1404 synchronized(this) {
1405 routerConfig.sendHostPolicies(strAddress);
1409 threads.add(policyThread);
1410 policyThread.start();
1411 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1413 // A thread for router
1414 Thread policyThread = new Thread(new Runnable() {
1416 synchronized(this) {
1417 routerConfig.sendRouterPolicies(strRouterAddress);
1421 threads.add(policyThread);
1422 policyThread.start();
1423 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1425 for (Thread thread : threads) {
1428 } catch (InterruptedException ex) {
1429 ex.printStackTrace();
1435 * A method to create a thread for policy deployment
1437 * @param setHostAddresses Set of strings for host addresses to configure
1440 private void createMACPolicyThreads(Set<String> setHostAddresses) throws IOException {
1442 // Create a list of threads
1443 List<Thread> threads = new ArrayList<Thread>();
1444 // Start threads for hosts
1445 for(String strAddress : setHostAddresses) {
1446 Thread policyThread = new Thread(new Runnable() {
1448 synchronized(this) {
1449 processJailConfig.sendMACPolicies(strAddress);
1453 threads.add(policyThread);
1454 policyThread.start();
1455 RuntimeOutput.print("Deploying MAC policies for: " + strAddress, BOOL_VERBOSE);
1458 for (Thread thread : threads) {
1461 } catch (InterruptedException ex) {
1462 ex.printStackTrace();
1469 * A method to send files to Java IoTSlave
1471 * @params strObjControllerName String
1472 * @params serverSocket ServerSocket
1473 * @params inStream ObjectInputStream communication
1474 * @params outStream ObjectOutputStream communication
1477 private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket,
1478 InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException {
1480 ObjectInputStream inStream = (ObjectInputStream) _inStream;
1481 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
1483 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1484 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1485 strControllerJarName;
1486 File file = new File(strControllerJarNamePath);
1487 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1488 "Sending file!", inStream, outStream);
1489 // Send file - Class file for object creation
1490 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1491 Message msgReply = (Message) inStream.readObject();
1492 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1493 // Send .zip file if additional zip file is specified
1494 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1495 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1496 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1497 if (strAdditionalFile.equals(STR_YES)) {
1498 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1499 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1500 strControllerCmpName;
1501 file = new File(strControllerCmpNamePath);
1502 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1503 "Sending file!", inStream, outStream);
1504 // Send file - Class file for object creation
1505 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1506 msgReply = (Message) inStream.readObject();
1507 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1513 * A method to send files to C++ IoTSlave
1516 * TODO: Need to look into this (as of now, file transferred retains the "data" format,
1517 * hence it is unreadable from outside world
1519 private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket,
1520 InputStream inStream, OutputStream outStream) throws IOException {
1522 sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream);
1524 sendString(sFileName, outStream); recvAck(inStream);
1525 File file = new File(sFilePath + sFileName);
1526 int iFileLen = toIntExact(file.length());
1527 RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
1529 sendInteger(iFileLen, outStream); recvAck(inStream);
1530 RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
1531 byte[] bytFile = new byte[iFileLen];
1532 InputStream inFileStream = new FileInputStream(file);
1533 RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
1535 OutputStream outFileStream = fileSocket.getOutputStream();
1536 RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
1538 while ((iCount = inFileStream.read(bytFile)) > 0) {
1539 outFileStream.write(bytFile, 0, iCount);
1541 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
1547 * A method to send files to C++ IoTSlave (now master using Process() to start
1548 * file transfer using scp)
1552 private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException {
1554 // Construct shell command to transfer file
1555 String sFile = sFilePath + sFileName;
1556 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR;
1557 runCommand(strCmdSend);
1558 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
1560 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1561 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
1562 runCommand(strCmdUnzip);
1563 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
1568 * runCommand() method runs shell command
1570 * @param strCommand String that contains command line
1573 private void runCommand(String strCommand) {
1576 Runtime runtime = Runtime.getRuntime();
1577 Process process = runtime.exec(strCommand);
1579 } catch (IOException ex) {
1580 System.out.println("RouterConfig: IOException: " + ex.getMessage());
1581 ex.printStackTrace();
1582 } catch (InterruptedException ex) {
1583 System.out.println("RouterConfig: InterruptException: " + ex.getMessage());
1584 ex.printStackTrace();
1590 * Construct command line for Java IoTSlave
1594 private String getCmdJavaIoTSlave(String strObjControllerName) {
1596 // Create an Shell executable
1597 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_JVM_INIT_HEAP_SIZE + " " +
1598 STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " +
1599 strIoTMasterHostAdd + " " + commHan.getComPort(strObjControllerName) + " " +
1600 commHan.getRMIRegPort(strObjControllerName) + " " + commHan.getRMIStubPort(strObjControllerName) +
1601 " > " + STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1602 String shellFile = "./" + strObjControllerName + STR_SHELL_FILE_EXT;
1603 createWrapperShellScript(strJavaCommand, shellFile);
1604 // Send the file to the compute node
1605 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_RUNTIME_DIR;
1606 runCommand(strCmdSend);
1607 System.out.println("IoTMaster: Sending main controller shell file: " + strCmdSend);
1608 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
1613 * Construct command line for C++ IoTSlave
1617 private String getCmdCppIoTSlave(String strObjControllerName) {
1619 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1620 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
1621 commHan.getComPort(strObjControllerName) + " " + strObjControllerName;
1626 * sendInteger() sends an integer in bytes
1628 public void sendInteger(int intSend, OutputStream outStream) throws IOException {
1630 BufferedOutputStream output = (BufferedOutputStream) outStream;
1631 // Transform integer into bytes
1632 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
1634 // Send the byte array
1635 output.write(bb.array(), 0, INT_SIZE);
1641 * recvInteger() receives integer in bytes
1643 public int recvInteger(InputStream inStream) throws IOException {
1645 BufferedInputStream input = (BufferedInputStream) inStream;
1646 // Wait until input is available
1647 while(input.available() == 0);
1648 // Read integer - 4 bytes
1649 byte[] recvInt = new byte[INT_SIZE];
1650 input.read(recvInt, 0, INT_SIZE);
1651 int retVal = ByteBuffer.wrap(recvInt).getInt();
1658 * recvString() receives String in bytes
1660 public String recvString(InputStream inStream) throws IOException {
1662 BufferedInputStream input = (BufferedInputStream) inStream;
1663 int strLen = recvInteger(inStream);
1664 // Wait until input is available
1665 while(input.available() == 0);
1666 // Read String per strLen
1667 byte[] recvStr = new byte[strLen];
1668 input.read(recvStr, 0, strLen);
1669 String retVal = new String(recvStr);
1676 * sendString() sends a String in bytes
1678 public void sendString(String strSend, OutputStream outStream) throws IOException {
1680 BufferedOutputStream output = (BufferedOutputStream) outStream;
1681 // Transform String into bytes
1682 byte[] strSendBytes = strSend.getBytes();
1683 int strLen = strSend.length();
1684 // Send the string length first
1685 sendInteger(strLen, outStream);
1686 // Send the byte array
1687 output.write(strSendBytes, 0, strLen);
1693 * Convert integer to enum
1695 public IoTCommCode getCode(int intCode) throws IOException {
1697 IoTCommCode[] commCode = IoTCommCode.values();
1698 IoTCommCode retCode = commCode[intCode];
1707 public synchronized boolean recvAck(InputStream inStream) throws IOException {
1709 int intAck = recvInteger(inStream);
1710 IoTCommCode codeAck = getCode(intAck);
1711 if (codeAck == IoTCommCode.ACKNOWLEDGED)
1721 public void sendEndTransfer(OutputStream outStream) throws IOException {
1723 int endCode = IoTCommCode.END_TRANSFER.ordinal();
1724 sendInteger(endCode, outStream);
1729 * Send communication code to C++
1731 public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException {
1734 IoTCommCode commCode = inpCommCode;
1735 int intCode = commCode.ordinal();
1736 // TODO: delete this later
1737 System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode);
1738 sendInteger(intCode, outStream); recvAck(inStream);
1743 * Create a main controller object for C++
1745 public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException {
1747 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
1748 String strMainObjName = strObjControllerName;
1749 sendString(strMainObjName, outStream); recvAck(inStream);
1750 RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
1755 * A helper function that converts Class into String
1757 * @param strDataType String MySQL data type
1760 public String getClassConverted(Class<?> cls) {
1762 if (cls == String.class) {
1764 } else if (cls == int.class) {
1773 * A helper function that converts Object into String for transfer to C++ slave
1775 * @param obj Object to be converted
1776 * @param strClassType String Java Class type
1779 public String getObjectConverted(Object obj) {
1781 if (obj instanceof String) {
1782 return (String) obj;
1783 } else if (obj instanceof Integer) {
1784 return Integer.toString((Integer) obj);
1792 * Create a driver object for C++
1794 public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd,
1795 Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses,
1796 OutputStream outStream, InputStream inStream) throws IOException {
1798 sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
1799 RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
1800 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
1801 sendString(strObjName, outStream); recvAck(inStream);
1802 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
1803 sendString(strObjClassName, outStream); recvAck(inStream);
1804 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
1805 sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
1806 RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
1807 sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
1808 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1809 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1810 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1811 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1812 int numOfArgs = arrFieldValues.length;
1813 RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
1814 sendInteger(numOfArgs, outStream); recvAck(inStream);
1815 for(Object obj : arrFieldValues) {
1816 String str = getObjectConverted(obj);
1817 sendString(str, outStream); recvAck(inStream);
1819 RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
1820 for(Class cls : arrFieldClasses) {
1821 String str = getClassConverted(cls);
1822 sendString(str, outStream); recvAck(inStream);
1828 * Create new IoTSet for C++
1830 public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1832 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
1833 RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
1834 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1835 sendString(strObjFieldName, outStream); recvAck(inStream);
1840 * Create new IoTRelation for C++
1842 public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1844 sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
1845 RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
1846 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1847 sendString(strObjFieldName, outStream); recvAck(inStream);
1852 * Get a IoTDeviceAddress object for C++
1854 public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream,
1855 String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
1857 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
1858 RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
1859 sendString(strDeviceAddress, outStream); recvAck(inStream);
1860 sendInteger(iSourcePort, outStream); recvAck(inStream);
1861 sendInteger(iDestPort, outStream); recvAck(inStream);
1862 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
1863 sendInteger(iSourceWildCard, outStream); recvAck(inStream);
1864 int iDestWildCard = (bDestWildCard ? 1 : 0);
1865 sendInteger(iDestWildCard, outStream); recvAck(inStream);
1866 RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
1871 * Get a IoTSet content object for C++
1873 public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName,
1874 String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort,
1875 OutputStream outStream, InputStream inStream) throws IOException {
1877 sendCommCode(iotCommCode, outStream, inStream);
1878 RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
1880 RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
1881 sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
1882 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
1883 sendString(strObjectName, outStream); recvAck(inStream);
1884 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
1885 sendString(strObjectClassName, outStream); recvAck(inStream);
1886 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
1887 sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
1888 RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
1889 sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
1890 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1891 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1892 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1893 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1898 * Reinitialize IoTRelation field for C++
1900 private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1902 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
1903 sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
1904 RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
1909 * Reinitialize IoTSet field for C++
1911 private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1913 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
1914 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
1915 RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
1920 * Create driver object for C++
1922 private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
1924 sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
1925 RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
1930 * Invoke init() for C++
1932 private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
1934 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
1935 RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
1940 * End session for C++
1942 public void endSessionCpp(OutputStream outStream) throws IOException {
1944 // Send message to end session
1945 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
1946 int intCode = endSessionCode.ordinal();
1947 sendInteger(intCode, outStream);
1948 //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
1949 RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
1954 * A method to assign objects to multiple JVMs, including
1955 * the controller/device object that uses other objects
1956 * in IoTSet and IoTRelation
1960 private void createObjects() {
1967 // Extract hostname for this IoTMaster from MySQL DB
1968 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1969 // Assign a new list of PrintWriter objects
1970 routerConfig.renewPrintWriter();
1971 HashSet<String> setAddresses = null;
1972 // Loop as we can still find controller/device classes
1973 for(int i=0; i<strObjectNames.length; i++) {
1975 start = System.currentTimeMillis();
1976 // Assign a new list of main PrintWriter objects
1977 routerConfig.renewMainPrintWriter();
1978 // Get controller names one by one
1979 String strObjControllerName = strObjectNames[i];
1980 // Use LoadBalancer to assign a host address
1981 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1982 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1983 if (strIoTSlaveControllerHostAdd == null)
1984 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1985 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1986 // Add port connection and get port numbers
1987 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1988 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1989 // ROUTING POLICY: IoTMaster and main controller object
1990 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1991 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1992 // ROUTING POLICY: Send the same routing policy to both the hosts
1993 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1994 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1995 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1996 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1998 String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
1999 STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
2000 if(STR_LANGUAGE_CONTROLLER == null)
2001 throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
2002 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
2003 String strSSHCommand = null;
2004 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2005 strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
2006 else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
2007 strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
2009 throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
2010 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
2011 createThread(strSSHCommand);
2012 // Wait for connection
2013 // Create a new socket for communication
2014 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
2015 Socket socket = serverSocket.accept();
2016 InputStream inStream = null;
2017 OutputStream outStream = null;
2018 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2019 inStream = new ObjectInputStream(socket.getInputStream());
2020 outStream = new ObjectOutputStream(socket.getOutputStream());
2021 } else { // At this point the language is certainly C++, otherwise would've complained above
2022 inStream = new BufferedInputStream(socket.getInputStream());
2023 outStream = new BufferedOutputStream(socket.getOutputStream());
2026 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
2027 // Send files for every controller class
2028 // e.g. AcmeProximity.jar and AcmeProximity.zip
2029 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
2030 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
2031 strControllerClassName;
2033 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2034 sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
2035 // Create main controller/device object
2036 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
2037 "Create main object!", inStream, outStream);
2039 String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT;
2040 String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/";
2041 sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
2042 createMainObjectCpp(strObjControllerName, outStream, inStream);
2044 // Write basic MAC policies for controller
2045 //String strFileName = STR_MAC_POL_PATH + strObjControllerName + STR_MAC_POLICY_EXT;
2046 if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
2047 String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT;
2048 processJailConfig.configureProcessJailControllerPolicies(strObjControllerName, strFileName,
2049 strIoTMasterHostAdd, commHan.getComPort(strObjControllerName));
2050 // Whether or not we need additional Tomoyo policy?
2051 String strAddMACPolicy = parseConfigFile(strControllerCfg, STR_ADD_MAC_POL);
2052 if (strAddMACPolicy != null && strAddMACPolicy.equals("Yes")) {
2053 String strContMACCfg = STR_CONT_PATH + strObjControllerName + "/";
2054 processJailConfig.combineAdditionalMACPolicy(strContMACCfg, strObjControllerName, strObjControllerName);
2057 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
2058 // Instrumenting one file
2059 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
2060 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
2061 HashMap<String,Object> hmControllerFieldObjects = null;
2062 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2063 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
2064 ClassReader cr = new ClassReader(fis);
2065 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
2066 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
2069 hmControllerFieldObjects = crim.getFieldObjects();
2071 String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
2072 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE);
2073 hmControllerFieldObjects = crim.getFieldObjects();
2075 // Get the object and the class names
2076 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
2077 //HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
2078 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
2079 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
2080 // Iterate over HashMap and choose between processing
2081 // SetInstrumenter vs. RelationInstrumenter
2082 String strFieldName = map.getKey();
2083 String strClassName = map.getValue().getClass().getName();
2084 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
2085 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
2086 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
2087 String strErrMsg = "IoTMaster: Controller object" +
2088 " cannot have IoTSet<IoTDeviceAddress>!";
2089 throw new Error(strErrMsg);
2090 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
2091 String strErrMsg = "IoTMaster: Controller object" +
2092 " cannot have IoTSet<ZigbeeAddress>!";
2093 throw new Error(strErrMsg);
2094 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
2095 // Instrument the IoTAddress
2096 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd, strObjControllerName);
2097 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
2100 instrumentIoTSet(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER);
2102 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
2103 instrumentIoTRelation(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER);
2106 // Combine controller MAC policies with the main policy file for the host
2107 String strTempFileName = "./" + strObjControllerName + STR_MAC_POLICY_EXT;
2108 processJailConfig.combineControllerMACPolicies(strIoTSlaveControllerHostAdd, strObjControllerName, strTempFileName);
2109 processJailConfig.flush();
2110 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
2111 for(String s: commHan.getHosts()) {
2112 setHostBasicPolicies(s);
2114 // We retain all the basic policies for router,
2115 // but we delete the initial allowance policies for internal all TCP and UDP communications
2116 setRouterBasicPolicies(STR_ROUTER_ADD);
2117 routerConfig.closeMain();
2118 // Deploy the policy
2119 setAddresses = new HashSet<String>(commHan.getHosts());
2120 setAddresses.add(strIoTMasterHostAdd);
2121 // See if firewall policy is configured to be "on" or "off"
2122 if (STR_POLICY_ON.equals(STR_YES))
2123 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
2124 // Separating object creations and Set/Relation initializations
2125 createDriverObjects();
2126 // Sets and relations initializations
2127 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2128 initializeSetsAndRelationsJava(inStream, outStream);
2130 initializeSetsAndRelationsCpp(inStream, outStream);;
2131 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2132 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
2133 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
2135 invokeInitMethodCpp(outStream, inStream);
2136 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
2137 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2138 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
2139 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
2140 } else // C++ side will wait until the program finishes, it's not generating a separate thread for now
2141 //endSessionCpp(outStream);
2145 serverSocket.close();
2146 objInitHand.clearObjectInitHandler();
2147 commHan.printLists();
2148 commHan.clearCommunicationHandler();
2149 lbIoT.printHostInfo();
2151 // Close access to policy files and deploy policies
2152 routerConfig.close();
2153 processJailConfig.close();
2154 if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
2155 createMACPolicyThreads(setAddresses);
2157 } catch (IOException |
2158 InterruptedException |
2159 ClassNotFoundException ex) {
2160 System.out.println("IoTMaster: Exception: "
2162 ex.printStackTrace();
2166 public static void main(String args[]) {
2168 // Detect the available controller/device classes
2169 // Input args[] should be used to list the controllers/devices
2170 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
2171 IoTMaster iotMaster = new IoTMaster(args);
2173 iotMaster.parseIoTMasterConfigFile();
2174 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
2175 iotMaster.initLiveDataStructure();
2177 iotMaster.createObjects();