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 boolean BOOL_VERBOSE;
109 * IoTMaster class constants
111 * Name constants - not to be configured by users
113 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
114 private static final String STR_CFG_FILE_EXT = ".config";
115 private static final String STR_CLS_FILE_EXT = ".class";
116 private static final String STR_JAR_FILE_EXT = ".jar";
117 private static final String STR_MAC_POLICY_EXT = ".tomoyo.pol";
118 private static final String STR_SHELL_FILE_EXT = ".sh";
119 private static final String STR_SO_FILE_EXT = ".so";
120 private static final String STR_ZIP_FILE_EXT = ".zip";
121 private static final String STR_TCP_PROTOCOL = "tcp";
122 private static final String STR_UDP_PROTOCOL = "udp";
123 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
124 private static final String STR_NO_PROTOCOL = "nopro";
125 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
126 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
127 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
128 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
129 private static final String STR_LANGUAGE = "LANGUAGE";
130 private static final String STR_ADD_MAC_POL = "ADDITIONAL_MAC_POLICY";
131 private static final String STR_YES = "Yes";
132 private static final String STR_NO = "No";
133 private static final String STR_JAVA = "Java";
134 private static final String STR_CPP = "C++";
135 private static final String STR_SSH = "ssh";
136 private static final String STR_SCP = "scp";
137 private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
138 private static final String STR_SHELL_HEADER = "#!/bin/sh";
139 private static final String STR_JAVA_PATH = "/usr/bin/java";
140 private static final String STR_MAC_POL_PATH = "tomoyo/";
142 private static int INT_SIZE = 4; // send length in the size of integer (4 bytes)
143 private static final int INT_DNS_PORT = 53;
146 * Runtime class name constants - not to be configured by users
148 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
149 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
150 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
151 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
152 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
153 private static final String STR_IOT_ADD_CLS = "IoTAddress";
159 public IoTMaster(String[] argObjNms) {
164 processJailConfig = null;
166 objAddInitHand = null;
167 strObjectNames = argObjNms;
169 strObjClassName = null;
170 strObjClassInterfaceName = null;
171 strObjStubClsIntfaceName = null;
172 strIoTMasterHostAdd = null;
173 strIoTSlaveControllerHostAdd = null;
174 strIoTSlaveObjectHostAdd = null;
175 arrFieldClasses = null;
176 arrFieldValues = null;
178 mapClassNameToCrim = null;
179 // Connection with C++ IoTSlave
180 serverSocketCpp = null;
185 STR_MASTER_MAC_ADD = null;
186 STR_IOT_CODE_PATH = null;
187 STR_CONT_PATH = null;
188 STR_RUNTIME_DIR = null;
189 STR_SLAVE_DIR = null;
192 STR_RMI_HOSTNAME = null;
193 STR_LOG_FILE_PATH = null;
195 STR_ROUTER_ADD = null;
196 STR_MONITORING_HOST = null;
197 STR_ZB_GATEWAY_ADDRESS = null;
198 STR_ZB_GATEWAY_PORT = null;
199 STR_ZB_IOTMASTER_PORT = null;
200 STR_JVM_INIT_HEAP_SIZE = null;
201 STR_JVM_MAX_HEAP_SIZE = null;
202 STR_LANGUAGE_CONTROLLER = null;
203 STR_ACTIVATE_SANDBOXING = null;
204 BOOL_VERBOSE = false;
208 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
212 private void initLiveDataStructure() {
214 commHan = new CommunicationHandler(BOOL_VERBOSE);
215 lbIoT = new LoadBalancer(BOOL_VERBOSE);
216 lbIoT.setupLoadBalancer();
217 routerConfig = new RouterConfig();
218 routerConfig.getAddressList(STR_ROUTER_ADD);
219 processJailConfig = new ProcessJailConfig();
220 //processJailConfig.setAddressListObject(routerConfig.getAddressListObject());
221 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
222 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
223 mapClassNameToCrim = new HashMap<String,Object>();
227 * getPrintWriter() gets a new PrintWriter for a new object
229 * @param strObjectName String object name
230 * @return PrintWriter
232 private PrintWriter getPrintWriter(String strObjectName) {
234 FileWriter fw = null;
236 fw = new FileWriter(strObjectName);
237 } catch (IOException ex) {
238 ex.printStackTrace();
240 PrintWriter printWriter = new PrintWriter(new BufferedWriter(fw));
245 * A method to initialize constants from config file
249 private void parseIoTMasterConfigFile() {
250 // Parse configuration file
251 Properties prop = new Properties();
252 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
253 File file = new File(strCfgFileName);
254 FileInputStream fis = null;
256 fis = new FileInputStream(file);
259 } catch (IOException ex) {
260 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
261 ex.printStackTrace();
263 // Initialize constants from config file
264 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
265 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
266 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
267 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
268 STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR");
269 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
270 STR_RMI_PATH = prop.getProperty("RMI_PATH");
271 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
272 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
273 STR_USERNAME = prop.getProperty("USERNAME");
274 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
275 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
276 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
277 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
278 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
279 STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
280 STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
281 STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
282 STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
283 STR_ACTIVATE_SANDBOXING = prop.getProperty("ACTIVATE_SANDBOXING");
284 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
288 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
289 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
290 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
291 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
292 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
293 RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE);
294 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
295 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
296 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
297 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
298 RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE);
299 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
300 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
301 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
302 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
303 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
304 RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
305 RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
306 RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
307 RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
308 RuntimeOutput.print("STR_ACTIVATE_SANDBOXING=" + STR_ACTIVATE_SANDBOXING, BOOL_VERBOSE);
309 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
310 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
314 * A method to parse information from a config file
316 * @param strCfgFileName Config file name
317 * @param strCfgField Config file field name
320 private String parseConfigFile(String strCfgFileName, String strCfgField) {
321 // Parse configuration file
322 Properties prop = new Properties();
323 File file = new File(strCfgFileName);
324 FileInputStream fis = null;
326 fis = new FileInputStream(file);
329 } catch (IOException ex) {
330 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
331 ex.printStackTrace();
333 System.out.println("IoTMaster: Reading " + strCfgField +
334 " from config file: " + strCfgFileName + " with value: " +
335 prop.getProperty(strCfgField, null));
336 // NULL is returned if the property isn't found
337 return prop.getProperty(strCfgField, null);
341 * A method to send files from IoTMaster
343 * @param filesocket File socket object
344 * @param sFileName File name
345 * @param lFLength File length
348 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
350 File file = new File(sFileName);
351 byte[] bytFile = new byte[toIntExact(lFLength)];
352 InputStream inFileStream = new FileInputStream(file);
354 OutputStream outFileStream = filesocket.getOutputStream();
356 while ((iCount = inFileStream.read(bytFile)) > 0) {
357 outFileStream.write(bytFile, 0, iCount);
360 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
364 * A method to create a thread
366 * @param sSSHCmd SSH command
369 private void createThread(String sSSHCmd) throws IOException {
371 // Start a new thread to start a new JVM
373 Runtime runtime = Runtime.getRuntime();
374 Process process = runtime.exec(sSSHCmd);
376 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
380 * A method to send command from master and receive reply from slave
382 * @params msgSend Message object
383 * @params strPurpose String that prints purpose message
384 * @params inStream Input stream
385 * @params outStream Output stream
388 private void commMasterToSlave(Message msgSend, String strPurpose,
389 InputStream _inStream, OutputStream _outStream)
390 throws IOException, ClassNotFoundException {
392 // Send message/command from master
393 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
394 outStream.writeObject(msgSend);
395 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
397 // Get reply from slave as acknowledgment
398 ObjectInputStream inStream = (ObjectInputStream) _inStream;
399 Message msgReply = (Message) inStream.readObject();
400 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
404 * A private method to instrument IoTSet device
406 * @params strFieldIdentifier String field name + object ID
407 * @params strFieldName String field name
408 * @params strIoTSlaveObjectHostAdd String slave host address
409 * @params inStream ObjectInputStream communication
410 * @params inStream ObjectOutputStream communication
411 * @params strLanguage String language
414 private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
415 InputStream inStream, OutputStream outStream, String strLanguage)
416 throws IOException, ClassNotFoundException, InterruptedException {
418 // Get information from the set
419 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
420 RuntimeOutput.print("IoTMaster: DEBUG: Getting into instrumentIoTSetDevice!", BOOL_VERBOSE);
421 // Create a new IoTSet
422 if(strLanguage.equals(STR_JAVA)) {
423 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
424 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
426 createNewIoTSetCpp(strFieldName, outStream, inStream);
427 int iRows = listObject.size();
428 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
429 // Transfer the address
430 for(int iRow=0; iRow<iRows; iRow++) {
431 arrFieldValues = listObject.get(iRow);
432 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
433 String strDeviceAddress = null;
434 String strDeviceAddressKey = null;
435 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
436 strDeviceAddress = strIoTSlaveObjectHostAdd;
437 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
439 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
440 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
442 int iDestDeviceDriverPort = (int) arrFieldValues[1];
443 String strProtocol = (String) arrFieldValues[2];
444 // Check for wildcard feature
445 boolean bSrcPortWildCard = false;
446 boolean bDstPortWildCard = false;
447 if (arrFieldValues.length > 3) {
448 bSrcPortWildCard = (boolean) arrFieldValues[3];
449 bDstPortWildCard = (boolean) arrFieldValues[4];
451 // Add the port connection into communication handler - if it's not assigned yet
452 if (commHan.getComPort(strDeviceAddressKey) == null) {
453 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
457 System.out.println("\n\n DEBUG: InstrumentSetDevice: Object Name: " + strObjName);
458 System.out.println("DEBUG: InstrumentSetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
459 System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n");
461 // Send address one by one
462 if(strLanguage.equals(STR_JAVA)) {
463 Message msgGetIoTSetObj = null;
464 if (bDstPortWildCard) {
465 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
466 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
467 strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
469 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
470 strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
471 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
473 getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort,
474 bSrcPortWildCard, bDstPortWildCard);
476 // Reinitialize IoTSet on device object
477 if(strLanguage.equals(STR_JAVA))
478 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
480 reinitializeIoTSetFieldCpp(outStream, inStream);
485 * A private method to instrument IoTSet Zigbee device
487 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
488 * @params strFieldName String field name
489 * @params strIoTSlaveObjectHostAdd String slave host address
490 * @params inStream ObjectInputStream communication
491 * @params inStream ObjectOutputStream communication
492 * @params strLanguage String language
495 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
496 InputStream inStream, OutputStream outStream, String strLanguage)
497 throws IOException, ClassNotFoundException, InterruptedException {
499 // Get information from the set
500 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
501 // Create a new IoTSet
502 if(strLanguage.equals(STR_JAVA)) {
503 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
504 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
505 } else // TODO: will need to implement IoTSet Zigbee for C++ later
507 // Prepare ZigbeeConfig
508 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
509 String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress;
510 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
511 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
512 commHan.addDevicePort(iZigbeeIoTMasterPort);
513 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
515 // Add the port connection into communication handler - if it's not assigned yet
516 if (commHan.getComPort(strZigbeeGWAddressKey) == null) {
517 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey);
519 int iRows = setInstrumenter.numberOfRows();
520 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
523 System.out.println("\n\nDEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
524 System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey));
525 System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n");
527 // Transfer the address
528 for(int iRow=0; iRow<iRows; iRow++) {
529 arrFieldValues = setInstrumenter.fieldValues(iRow);
530 // Get device address
531 String strZBDevAddress = (String) arrFieldValues[0];
532 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
533 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
534 // Send address one by one
535 if(strLanguage.equals(STR_JAVA)) {
536 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
537 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
538 } else // TODO: Implement IoTSet Zigbee for C++
541 zbConfig.closeConnection();
542 // Reinitialize IoTSet on device object
543 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
548 * A private method to instrument IoTSet of addresses
550 * @params strFieldIdentifier String field name + object ID
551 * @params strFieldName String field name
552 * @params inStream ObjectInputStream communication
553 * @params inStream ObjectOutputStream communication
554 * @params strLanguage String language
557 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
558 InputStream inStream, OutputStream outStream, String strLanguage)
559 throws IOException, ClassNotFoundException, InterruptedException {
561 // Get information from the set
562 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
563 // Create a new IoTSet
564 if(strLanguage.equals(STR_JAVA)) {
565 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
566 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
569 int iRows = listObject.size();
570 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
571 // Transfer the address
572 for(int iRow=0; iRow<iRows; iRow++) {
573 arrFieldValues = listObject.get(iRow);
574 // Get device address
575 String strAddress = (String) arrFieldValues[0];
576 // Send address one by one
577 if(strLanguage.equals(STR_JAVA)) {
578 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
579 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
580 } else // TODO: Implement IoTSet Address for C++
583 // Reinitialize IoTSet on device object
584 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
585 "Reinitialize IoTSet fields!", inStream, outStream);
590 * A private method to instrument an object on a specific machine and setting up policies
592 * @params strFieldObjectID String field object ID
593 * @params strObjControllerName String object controller name
594 * @params strLanguage String language
597 private void instrumentObject(String strFieldObjectID, String strObjControllerName, String strLanguage) throws IOException {
599 // Extract the interface name for RMI
600 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
602 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
603 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
604 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
605 // Create an object name, e.g. ProximitySensorImplPS1
606 strObjName = strObjClassName + strFieldObjectID;
607 // Check first if host exists
608 if(commHan.objectExists(strObjName)) {
609 // If this object exists already ...
610 // Re-read IoTSlave object hostname for further reference
611 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
612 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
614 // If this is a new object ... then create one
615 // Get host address for IoTSlave from LoadBalancer
616 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
617 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
618 if (strIoTSlaveControllerHostAdd == null)
619 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
620 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
621 // Add port connection and get port numbers
622 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
623 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
624 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
625 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
626 // ROUTING POLICY: IoTMaster and device/controller object
627 // Master-slave communication
628 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
629 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
630 // ROUTING POLICY: Send the same routing policy to both the hosts
631 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
632 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
633 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
634 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
635 // Need to accommodate callback functions here - open ports for TCP
636 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
637 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
638 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
639 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
640 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
641 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
642 // Configure MAC policies for objects
643 //String strFileName = STR_MAC_POL_PATH + strObjClassName + STR_MAC_POLICY_EXT;
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);
724 System.out.println("\n\n DEBUG: InstrumentPolicySetDevice: Object Name: " + strObjName);
725 System.out.println("DEBUG: InstrumentPolicySetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
726 System.out.println("DEBUG: InstrumentPolicySetDevice: Device address: " + strDeviceAddressKey + "\n\n");
728 // Send routing policy to router for device drivers and devices
729 // ROUTING POLICY: RMI communication - RMI registry and stub ports
730 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
731 // Port number -1 means that we don't set the policy strictly to port number level
732 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
733 // ROUTING POLICY: Device driver and device
734 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
735 // ROUTING POLICY: Send to the compute node where the device driver is
736 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
737 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
738 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
739 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
740 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
741 // This is a TCP protocol that connects, e.g. a phone to our runtime system
742 // that provides a gateway access (accessed through destination port number)
743 commHan.addDevicePort(iDestDeviceDriverPort);
744 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
745 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
746 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
747 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
748 // Configure MAC policies
749 if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
750 processJailConfig.configureProcessJailGWDevicePolicies(strIoTSlaveObjectHostAdd, STR_ROUTER_ADD, strDeviceAddress, INT_DNS_PORT);
752 // Other port numbers...
753 commHan.addDevicePort(iDestDeviceDriverPort);
754 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
755 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
756 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
757 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
758 // Configure MAC policies
759 if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
760 processJailConfig.configureProcessJailDevicePolicies(strIoTSlaveObjectHostAdd, strProtocol,
761 commHan.getComPort(strDeviceAddressKey), strDeviceAddress, iDestDeviceDriverPort);
767 * A private method to set router policies for IoTAddress objects
769 * @params strFieldIdentifier String field name + object ID
770 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
771 * @params strHostAddress String host address
774 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
775 String strHostAddress, String strControllerName) {
777 // Get information from the set
778 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
779 int iRows = setInstrumenter.numberOfRows();
780 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
781 // Transfer the address
782 for(int iRow=0; iRow<iRows; iRow++) {
783 arrFieldValues = setInstrumenter.fieldValues(iRow);
784 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
785 // Get device address
786 String strAddress = (String) arrFieldValues[0];
787 // Setting up router policies for HTTP/HTTPs
788 if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
789 if (strControllerName != null) {
790 processJailConfig.configureProcessJailInetAddressPolicies(strControllerName, STR_ROUTER_ADD, strAddress);
792 processJailConfig.configureProcessJailInetAddressPolicies(strHostAddress, STR_ROUTER_ADD, strAddress);
795 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
796 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
801 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
803 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
805 * @params strFieldObjectID String field object ID
806 * @params strLanguage String language
809 private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
811 // If this is a new object ... then create one
812 // Instrument the class source code and look for IoTSet for device addresses
813 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
814 HashMap<String,Object> hmObjectFieldObjects = null;
815 if(strLanguage.equals(STR_JAVA)) {
816 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
817 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
818 ClassReader cr = new ClassReader(fis);
819 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
820 // We need Object ID to instrument IoTDeviceAddress
821 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
824 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
825 hmObjectFieldObjects = crim.getFieldObjects();
827 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
828 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE);
829 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
830 hmObjectFieldObjects = crim.getFieldObjects();
832 // Get the object and the class names
833 // Build objects for IoTSet and IoTRelation fields in the device object classes
834 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
835 strFieldObjectID, BOOL_VERBOSE);
836 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
837 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
838 // Iterate over HashMap and choose between processing
839 String strFieldName = map.getKey();
840 String strClassName = map.getValue().getClass().getName();
841 String strFieldIdentifier = strFieldName + strFieldObjectID;
842 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
843 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
844 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
845 // Instrument the normal IoTDeviceAddress
846 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
847 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
848 // Instrument the IoTAddress
849 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd, null);
850 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
851 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
852 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
855 String strErrMsg = "IoTMaster: Device driver object" +
856 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
857 " or IoTSet<IoTZigbeeAddress>!";
858 throw new Error(strErrMsg);
861 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
862 throw new Error(strErrMsg);
869 * A private method to send files to a Java slave driver
871 * @params serverSocket ServerSocket
872 * @params _inStream InputStream
873 * @params _outStream OutputStream
874 * @params strObjName String
875 * @params strObjClassName String
876 * @params strObjClassInterfaceName String
877 * @params strObjStubClsIntfaceName String
878 * @params strIoTSlaveObjectHostAdd String
879 * @params strFieldObjectID String
880 * @params arrFieldValues Object[]
881 * @params arrFieldClasses Class[]
884 private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream,
885 String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
886 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
887 throws IOException, ClassNotFoundException {
889 ObjectInputStream inStream = (ObjectInputStream) _inStream;
890 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
891 // Create message to transfer file first
892 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
893 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
894 File file = new File(sPath);
895 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
896 "Sending file!", inStream, outStream);
897 // Send file - JAR file for object creation
898 sendFile(serverSocket.accept(), sPath, file.length());
899 Message msgReply = (Message) inStream.readObject();
900 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
901 // Pack object information to create object on a IoTSlave
902 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
903 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
904 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
906 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
911 * A private method to send files to a Java slave driver
915 private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd)
916 throws IOException, ClassNotFoundException {
918 // Create message to transfer file first
919 String sFileName = strObjClassName + STR_ZIP_FILE_EXT;
920 String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
921 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR;
922 runCommand(strCmdSend);
923 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
925 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
926 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
927 runCommand(strCmdUnzip);
928 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
934 * Construct command line for Java IoTSlave
938 private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
940 // Create an Shell executable
941 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " +
942 STR_RMI_HOSTNAME + strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
943 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
944 commHan.getRMIStubPort(strObjName) + " > " + STR_LOG_FILE_PATH + strObjName + ".log &";
945 String shellFile = "./" + strObjName + STR_SHELL_FILE_EXT;
946 createWrapperShellScript(strJavaCommand, shellFile);
947 // Send the file to the compute node
948 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_RUNTIME_DIR;
949 runCommand(strCmdSend);
950 System.out.println("IoTMaster: Sending shell file: " + strCmdSend);
951 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
956 * Construct command line for C++ IoTSlave
960 private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
962 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
963 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
964 commHan.getComPort(strObjName) + " " + strObjName;
969 * createWrapperShellScript() gets a wrapper shell script
971 * @param strCommand String command
972 * @param strObjectName String object name
973 * @return PrintWriter
975 private void createWrapperShellScript(String strCommand, String strFileName) {
977 PrintWriter printWriter = getPrintWriter(strFileName);
978 printWriter.println(strCommand);
980 runCommand("chmod 755 " + strFileName);
985 * A private method to create an object on a specific machine
987 * @params strObjName String object name
988 * @params strObjClassName String object class name
989 * @params strObjClassInterfaceName String object class interface name
990 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
991 * @params strFieldObjectID String field object ID
992 * @params arrFieldValues Array of field values
993 * @params arrFieldClasses Array of field classes
996 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
997 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
998 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
1001 String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
1002 String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
1003 if(strLanguageDriver == null) // Read just the field LANGUAGE if the first read is null
1004 strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
1005 if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
1006 throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
1011 start = System.currentTimeMillis();
1013 // Construct ssh command line
1014 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
1015 // java -cp $CLASSPATH:./*.jar
1016 // -Djava.rmi.server.codebase=file:./*.jar
1017 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
1018 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
1019 String strSSHCommand = null;
1020 if(strLanguageDriver.equals(STR_JAVA))
1021 strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
1022 else if(strLanguageDriver.equals(STR_CPP))
1023 strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
1025 throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
1026 RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
1028 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1029 // Start a new thread to start a new JVM
1030 createThread(strSSHCommand);
1031 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
1032 Socket socket = serverSocket.accept();
1033 //InputStream inStream = new ObjectInputStream(socket.getInputStream());
1034 //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
1035 InputStream inStream = null;
1036 OutputStream outStream = null;
1037 if(strLanguageDriver.equals(STR_JAVA)) {
1038 inStream = new ObjectInputStream(socket.getInputStream());
1039 outStream = new ObjectOutputStream(socket.getOutputStream());
1040 } else { // At this point the language is certainly C++, otherwise would've complained above
1041 inStream = new BufferedInputStream(socket.getInputStream());
1042 outStream = new BufferedOutputStream(socket.getOutputStream());
1047 result = System.currentTimeMillis()-start;
1048 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
1051 start = System.currentTimeMillis();
1053 if(strLanguageDriver.equals(STR_JAVA)) {
1054 sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName,
1055 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1056 strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
1058 sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd);
1059 createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd,
1060 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses,
1061 outStream, inStream);
1065 result = System.currentTimeMillis()-start;
1066 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
1069 start = System.currentTimeMillis();
1071 // Instrument the class source code and look for IoTSet for device addresses
1072 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
1073 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE);
1074 // Get the object and the class names
1075 // Build objects for IoTSet and IoTRelation fields in the device object classes
1076 Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
1077 HashMap<String,Object> hmObjectFieldObjects = null;
1078 if (crimObj instanceof ClassRuntimeInstrumenterMaster) {
1079 ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj;
1080 hmObjectFieldObjects = crim.getFieldObjects();
1081 } else if (crimObj instanceof CRuntimeInstrumenterMaster) {
1082 CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj;
1083 hmObjectFieldObjects = crim.getFieldObjects();
1085 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
1086 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1087 // Iterate over HashMap and choose between processing
1088 String strFieldName = map.getKey();
1089 String strClassName = map.getValue().getClass().getName();
1090 String strFieldIdentifier = strFieldName + strFieldObjectID;
1091 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1092 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1093 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1094 // Instrument the normal IoTDeviceAddress
1095 synchronized(this) {
1096 //RuntimeOutput.print("IoTMaster: DEBUG: Processing " + STR_IOT_DEV_ADD_CLS + "!", BOOL_VERBOSE);
1097 instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1099 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1100 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
1101 synchronized(this) {
1102 instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1104 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1105 // Instrument the IoTAddress
1106 synchronized(this) {
1107 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
1110 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
1111 " or IoTSet<IoTZigbeeAddress>!";
1112 throw new Error(strErrMsg);
1115 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
1116 throw new Error(strErrMsg);
1120 // TODO: Change this later
1121 if(strLanguageDriver.equals(STR_JAVA)) {
1122 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
1123 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1124 } else { // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
1125 createDriverObjectCpp(outStream, inStream);
1126 //endSessionCpp(outStream);
1130 result = System.currentTimeMillis()-start;
1131 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
1137 serverSocket.close();
1142 * A private method to create controller objects
1146 private void createDriverObjects() throws InterruptedException {
1148 // Create a list of threads
1149 List<Thread> threads = new ArrayList<Thread>();
1150 // Get the list of active controller objects and loop it
1151 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
1152 for(String strObjName : listActiveControllerObject) {
1154 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
1155 Thread objectThread = new Thread(new Runnable() {
1157 synchronized(this) {
1159 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
1160 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
1161 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
1162 commHan.getArrayFieldClasses(strObjName));
1163 } catch (IOException |
1164 ClassNotFoundException |
1165 InterruptedException ex) {
1166 ex.printStackTrace();
1171 threads.add(objectThread);
1172 objectThread.start();
1175 for (Thread thread : threads) {
1178 } catch (InterruptedException ex) {
1179 ex.printStackTrace();
1186 * A private method to instrument IoTSet
1188 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
1189 * @params strFieldName String field name
1190 * @params strLanguage String language
1193 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strObjControllerName, String strLanguage)
1194 throws IOException, ClassNotFoundException, InterruptedException {
1196 // Get information from the set
1197 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1198 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
1200 int iRows = setInstrumenter.numberOfRows();
1201 for(int iRow=0; iRow<iRows; iRow++) {
1202 // Get field classes and values
1203 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
1204 arrFieldValues = setInstrumenter.fieldValues(iRow);
1205 // Get object ID and class name
1206 String strObjID = setInstrumenter.fieldObjectID(iRow);
1207 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
1208 // Call the method to create an object
1209 instrumentObject(strObjID, strObjControllerName, strLanguage);
1210 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1211 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
1212 commHan.getRMIStubPort(strObjName));
1218 * A private method to instrument IoTRelation
1220 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
1221 * @params strFieldName String field name
1222 * @params strLanguage String language
1225 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strObjControllerName, String strLanguage)
1226 throws IOException, ClassNotFoundException, InterruptedException {
1228 // Get information from the set
1229 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
1230 int iRows = relationInstrumenter.numberOfRows();
1231 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
1233 for(int iRow=0; iRow<iRows; iRow++) {
1234 // Operate on the first set first
1235 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
1236 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
1237 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
1238 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
1239 // Call the method to create an object
1240 instrumentObject(strObjID, strObjControllerName, strLanguage);
1241 // Get the first object controller host address
1242 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1243 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1244 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1245 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1246 // Operate on the second set
1247 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
1248 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
1249 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
1250 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
1251 // Call the method to create an object
1252 instrumentObject(strObjID, strObjControllerName, strLanguage);
1253 // Get the second object controller host address
1254 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1255 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1256 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1257 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1258 // ROUTING POLICY: first and second controller objects in IoTRelation
1259 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
1260 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1261 // ROUTING POLICY: Send the same routing policy to both the hosts
1262 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1263 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1264 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1265 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1270 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1272 * @params inStream ObjectInputStream communication
1273 * @params outStream ObjectOutputStream communication
1276 private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream)
1277 throws IOException, ClassNotFoundException {
1278 // Get list of fields
1279 List<String> strFields = objInitHand.getListOfFields();
1280 // Iterate on HostAddress
1281 for(String str : strFields) {
1282 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1283 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1284 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1285 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
1286 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1287 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1288 for (ObjectInitInfo objInitInfo : listObject) {
1289 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1290 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1291 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
1292 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1293 "Get IoTSet object!", inStream, outStream);
1296 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1297 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1298 "Renitialize IoTSet field!", inStream, outStream);
1299 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1300 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1301 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1302 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1303 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1304 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1305 Iterator it = listSecondObject.iterator();
1306 for (ObjectInitInfo objInitInfo : listObject) {
1307 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1308 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
1309 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1310 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1311 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()),
1312 "Get IoTRelation first object!", inStream, outStream);
1313 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1314 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1315 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1316 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1317 objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1318 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()),
1319 "Get IoTRelation second object!", inStream, outStream);
1321 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1322 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1323 "Renitialize IoTRelation field!", inStream, outStream);
1329 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1331 * @params inStream ObjectInputStream communication
1332 * @params outStream ObjectOutputStream communication
1335 private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream)
1336 throws IOException, ClassNotFoundException {
1337 // Get list of fields
1338 List<String> strFields = objInitHand.getListOfFields();
1339 // Iterate on HostAddress
1340 for(String str : strFields) {
1341 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1342 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1343 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1344 createNewIoTSetCpp(str, outStream, inStream);
1345 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1346 for (ObjectInitInfo objInitInfo : listObject) {
1347 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1348 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1349 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1350 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1352 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1353 reinitializeIoTSetFieldCpp(outStream, inStream);
1354 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1355 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1356 // TODO: createNewIoTRelation needs to be created here!
1357 createNewIoTRelationCpp(str, outStream, inStream);
1358 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1359 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1360 Iterator it = listSecondObject.iterator();
1361 for (ObjectInitInfo objInitInfo : listObject) {
1362 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1363 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1364 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1365 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1366 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1367 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1368 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(),
1369 objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1370 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream);
1372 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1373 reinitializeIoTRelationFieldCpp(outStream, inStream);
1379 * A method to set router basic policies at once
1381 * @param strRouter String router name
1384 private void setRouterBasicPolicies(String strRouter) {
1386 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1387 routerConfig.initMainPolicy(strRouter);
1388 routerConfig.combineRouterPolicies(strRouter);
1389 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1390 routerConfig.configureRouterDHCPPolicies(strRouter);
1391 routerConfig.configureRouterDNSPolicies(strRouter);
1392 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1393 routerConfig.configureRejectPolicies(strRouter);
1397 * A method to set host basic policies at once
1399 * @param strHost String host name
1402 private void setHostBasicPolicies(String strHost) {
1404 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1405 routerConfig.initMainPolicy(strHost);
1406 routerConfig.combineRouterPolicies(strHost);
1407 routerConfig.configureHostDHCPPolicies(strHost);
1408 routerConfig.configureHostDNSPolicies(strHost);
1409 if (strHost.equals(strMonitorHost)) {
1410 // Check if this is the monitoring host
1411 routerConfig.configureHostICMPPolicies(strHost);
1412 routerConfig.configureHostSSHPolicies(strHost);
1414 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1415 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1417 // Apply SQL allowance policies to master host
1418 if (strHost.equals(strIoTMasterHostAdd)) {
1419 routerConfig.configureHostSQLPolicies(strHost);
1421 routerConfig.configureRejectPolicies(strHost);
1425 * A method to create a thread for policy deployment
1427 * @param strRouterAddress String router address to configure
1428 * @param setHostAddresses Set of strings for host addresses to configure
1431 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1433 // Create a list of threads
1434 List<Thread> threads = new ArrayList<Thread>();
1435 // Start threads for hosts
1436 for(String strAddress : setHostAddresses) {
1437 Thread policyThread = new Thread(new Runnable() {
1439 synchronized(this) {
1440 routerConfig.sendHostPolicies(strAddress);
1444 threads.add(policyThread);
1445 policyThread.start();
1446 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1448 // A thread for router
1449 Thread policyThread = new Thread(new Runnable() {
1451 synchronized(this) {
1452 routerConfig.sendRouterPolicies(strRouterAddress);
1456 threads.add(policyThread);
1457 policyThread.start();
1458 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1460 for (Thread thread : threads) {
1463 } catch (InterruptedException ex) {
1464 ex.printStackTrace();
1470 * A method to create a thread for policy deployment
1472 * @param setHostAddresses Set of strings for host addresses to configure
1475 private void createMACPolicyThreads(Set<String> setHostAddresses) throws IOException {
1477 // Create a list of threads
1478 List<Thread> threads = new ArrayList<Thread>();
1479 // Start threads for hosts
1480 for(String strAddress : setHostAddresses) {
1481 Thread policyThread = new Thread(new Runnable() {
1483 synchronized(this) {
1484 processJailConfig.sendMACPolicies(strAddress);
1488 threads.add(policyThread);
1489 policyThread.start();
1490 RuntimeOutput.print("Deploying MAC policies for: " + strAddress, BOOL_VERBOSE);
1493 for (Thread thread : threads) {
1496 } catch (InterruptedException ex) {
1497 ex.printStackTrace();
1504 * A method to send files to Java IoTSlave
1506 * @params strObjControllerName String
1507 * @params serverSocket ServerSocket
1508 * @params inStream ObjectInputStream communication
1509 * @params outStream ObjectOutputStream communication
1512 private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket,
1513 InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException {
1515 ObjectInputStream inStream = (ObjectInputStream) _inStream;
1516 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
1518 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1519 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1520 strControllerJarName;
1521 File file = new File(strControllerJarNamePath);
1522 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1523 "Sending file!", inStream, outStream);
1524 // Send file - Class file for object creation
1525 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1526 Message msgReply = (Message) inStream.readObject();
1527 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1528 // Send .zip file if additional zip file is specified
1529 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1530 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1531 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1532 if (strAdditionalFile.equals(STR_YES)) {
1533 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1534 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1535 strControllerCmpName;
1536 file = new File(strControllerCmpNamePath);
1537 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1538 "Sending file!", inStream, outStream);
1539 // Send file - Class file for object creation
1540 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1541 msgReply = (Message) inStream.readObject();
1542 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1548 * A method to send files to C++ IoTSlave
1551 * TODO: Need to look into this (as of now, file transferred retains the "data" format,
1552 * hence it is unreadable from outside world
1554 private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket,
1555 InputStream inStream, OutputStream outStream) throws IOException {
1557 sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream);
1559 sendString(sFileName, outStream); recvAck(inStream);
1560 File file = new File(sFilePath + sFileName);
1561 int iFileLen = toIntExact(file.length());
1562 RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
1564 sendInteger(iFileLen, outStream); recvAck(inStream);
1565 RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
1566 byte[] bytFile = new byte[iFileLen];
1567 InputStream inFileStream = new FileInputStream(file);
1568 RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
1570 OutputStream outFileStream = fileSocket.getOutputStream();
1571 RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
1573 while ((iCount = inFileStream.read(bytFile)) > 0) {
1574 outFileStream.write(bytFile, 0, iCount);
1576 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
1582 * A method to send files to C++ IoTSlave (now master using Process() to start
1583 * file transfer using scp)
1587 private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException {
1589 // Construct shell command to transfer file
1590 String sFile = sFilePath + sFileName;
1591 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR;
1592 runCommand(strCmdSend);
1593 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
1595 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1596 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
1597 runCommand(strCmdUnzip);
1598 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
1603 * runCommand() method runs shell command
1605 * @param strCommand String that contains command line
1608 private void runCommand(String strCommand) {
1611 Runtime runtime = Runtime.getRuntime();
1612 Process process = runtime.exec(strCommand);
1614 } catch (IOException ex) {
1615 System.out.println("RouterConfig: IOException: " + ex.getMessage());
1616 ex.printStackTrace();
1617 } catch (InterruptedException ex) {
1618 System.out.println("RouterConfig: InterruptException: " + ex.getMessage());
1619 ex.printStackTrace();
1625 * Construct command line for Java IoTSlave
1629 private String getCmdJavaIoTSlave(String strObjControllerName) {
1631 // Create an Shell executable
1632 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_JVM_INIT_HEAP_SIZE + " " +
1633 STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " +
1634 strIoTMasterHostAdd + " " + commHan.getComPort(strObjControllerName) + " " +
1635 commHan.getRMIRegPort(strObjControllerName) + " " + commHan.getRMIStubPort(strObjControllerName) +
1636 " > " + STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1637 String shellFile = "./" + strObjControllerName + STR_SHELL_FILE_EXT;
1638 createWrapperShellScript(strJavaCommand, shellFile);
1639 // Send the file to the compute node
1640 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_RUNTIME_DIR;
1641 runCommand(strCmdSend);
1642 System.out.println("IoTMaster: Sending main controller shell file: " + strCmdSend);
1643 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
1648 * Construct command line for C++ IoTSlave
1652 private String getCmdCppIoTSlave(String strObjControllerName) {
1654 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1655 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
1656 commHan.getComPort(strObjControllerName) + " " + strObjControllerName;
1661 * sendInteger() sends an integer in bytes
1663 public void sendInteger(int intSend, OutputStream outStream) throws IOException {
1665 BufferedOutputStream output = (BufferedOutputStream) outStream;
1666 // Transform integer into bytes
1667 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
1669 // Send the byte array
1670 output.write(bb.array(), 0, INT_SIZE);
1676 * recvInteger() receives integer in bytes
1678 public int recvInteger(InputStream inStream) throws IOException {
1680 BufferedInputStream input = (BufferedInputStream) inStream;
1681 // Wait until input is available
1682 while(input.available() == 0);
1683 // Read integer - 4 bytes
1684 byte[] recvInt = new byte[INT_SIZE];
1685 input.read(recvInt, 0, INT_SIZE);
1686 int retVal = ByteBuffer.wrap(recvInt).getInt();
1693 * recvString() receives String in bytes
1695 public String recvString(InputStream inStream) throws IOException {
1697 BufferedInputStream input = (BufferedInputStream) inStream;
1698 int strLen = recvInteger(inStream);
1699 // Wait until input is available
1700 while(input.available() == 0);
1701 // Read String per strLen
1702 byte[] recvStr = new byte[strLen];
1703 input.read(recvStr, 0, strLen);
1704 String retVal = new String(recvStr);
1711 * sendString() sends a String in bytes
1713 public void sendString(String strSend, OutputStream outStream) throws IOException {
1715 BufferedOutputStream output = (BufferedOutputStream) outStream;
1716 // Transform String into bytes
1717 byte[] strSendBytes = strSend.getBytes();
1718 int strLen = strSend.length();
1719 // Send the string length first
1720 sendInteger(strLen, outStream);
1721 // Send the byte array
1722 output.write(strSendBytes, 0, strLen);
1728 * Convert integer to enum
1730 public IoTCommCode getCode(int intCode) throws IOException {
1732 IoTCommCode[] commCode = IoTCommCode.values();
1733 IoTCommCode retCode = commCode[intCode];
1742 public synchronized boolean recvAck(InputStream inStream) throws IOException {
1744 int intAck = recvInteger(inStream);
1745 IoTCommCode codeAck = getCode(intAck);
1746 if (codeAck == IoTCommCode.ACKNOWLEDGED)
1756 public void sendEndTransfer(OutputStream outStream) throws IOException {
1758 int endCode = IoTCommCode.END_TRANSFER.ordinal();
1759 sendInteger(endCode, outStream);
1764 * Send communication code to C++
1766 public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException {
1769 IoTCommCode commCode = inpCommCode;
1770 int intCode = commCode.ordinal();
1771 // TODO: delete this later
1772 System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode);
1773 sendInteger(intCode, outStream); recvAck(inStream);
1778 * Create a main controller object for C++
1780 public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException {
1782 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
1783 String strMainObjName = strObjControllerName;
1784 sendString(strMainObjName, outStream); recvAck(inStream);
1785 RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
1790 * A helper function that converts Class into String
1792 * @param strDataType String MySQL data type
1795 public String getClassConverted(Class<?> cls) {
1797 if (cls == String.class) {
1799 } else if (cls == int.class) {
1808 * A helper function that converts Object into String for transfer to C++ slave
1810 * @param obj Object to be converted
1811 * @param strClassType String Java Class type
1814 public String getObjectConverted(Object obj) {
1816 if (obj instanceof String) {
1817 return (String) obj;
1818 } else if (obj instanceof Integer) {
1819 return Integer.toString((Integer) obj);
1827 * Create a driver object for C++
1829 public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd,
1830 Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses,
1831 OutputStream outStream, InputStream inStream) throws IOException {
1833 sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
1834 RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
1835 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
1836 sendString(strObjName, outStream); recvAck(inStream);
1837 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
1838 sendString(strObjClassName, outStream); recvAck(inStream);
1839 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
1840 sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
1841 RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
1842 sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
1843 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1844 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1845 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1846 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1847 int numOfArgs = arrFieldValues.length;
1848 RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
1849 sendInteger(numOfArgs, outStream); recvAck(inStream);
1850 for(Object obj : arrFieldValues) {
1851 String str = getObjectConverted(obj);
1852 sendString(str, outStream); recvAck(inStream);
1854 RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
1855 for(Class cls : arrFieldClasses) {
1856 String str = getClassConverted(cls);
1857 sendString(str, outStream); recvAck(inStream);
1863 * Create new IoTSet for C++
1865 public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1867 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
1868 RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
1869 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1870 sendString(strObjFieldName, outStream); recvAck(inStream);
1875 * Create new IoTRelation for C++
1877 public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1879 sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
1880 RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
1881 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1882 sendString(strObjFieldName, outStream); recvAck(inStream);
1887 * Get a IoTDeviceAddress object for C++
1889 public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream,
1890 String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
1892 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
1893 RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
1894 sendString(strDeviceAddress, outStream); recvAck(inStream);
1895 sendInteger(iSourcePort, outStream); recvAck(inStream);
1896 sendInteger(iDestPort, outStream); recvAck(inStream);
1897 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
1898 sendInteger(iSourceWildCard, outStream); recvAck(inStream);
1899 int iDestWildCard = (bDestWildCard ? 1 : 0);
1900 sendInteger(iDestWildCard, outStream); recvAck(inStream);
1901 RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
1906 * Get a IoTSet content object for C++
1908 public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName,
1909 String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort,
1910 OutputStream outStream, InputStream inStream) throws IOException {
1912 sendCommCode(iotCommCode, outStream, inStream);
1913 RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
1915 RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
1916 sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
1917 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
1918 sendString(strObjectName, outStream); recvAck(inStream);
1919 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
1920 sendString(strObjectClassName, outStream); recvAck(inStream);
1921 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
1922 sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
1923 RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
1924 sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
1925 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1926 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1927 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1928 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1933 * Reinitialize IoTRelation field for C++
1935 private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1937 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
1938 sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
1939 RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
1944 * Reinitialize IoTSet field for C++
1946 private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1948 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
1949 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
1950 RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
1955 * Create driver object for C++
1957 private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
1959 sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
1960 RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
1965 * Invoke init() for C++
1967 private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
1969 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
1970 RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
1975 * End session for C++
1977 public void endSessionCpp(OutputStream outStream) throws IOException {
1979 // Send message to end session
1980 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
1981 int intCode = endSessionCode.ordinal();
1982 sendInteger(intCode, outStream);
1983 //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
1984 RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
1989 * A method to assign objects to multiple JVMs, including
1990 * the controller/device object that uses other objects
1991 * in IoTSet and IoTRelation
1995 private void createObjects() {
2002 // Extract hostname for this IoTMaster from MySQL DB
2003 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
2004 // Assign a new list of PrintWriter objects
2005 routerConfig.renewPrintWriter();
2006 HashSet<String> setAddresses = null;
2007 // Loop as we can still find controller/device classes
2008 for(int i=0; i<strObjectNames.length; i++) {
2010 start = System.currentTimeMillis();
2011 // Assign a new list of main PrintWriter objects
2012 routerConfig.renewMainPrintWriter();
2013 // Get controller names one by one
2014 String strObjControllerName = strObjectNames[i];
2015 // Use LoadBalancer to assign a host address
2016 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
2017 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
2018 if (strIoTSlaveControllerHostAdd == null)
2019 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
2020 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
2021 // Add port connection and get port numbers
2022 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
2023 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
2024 // ROUTING POLICY: IoTMaster and main controller object
2025 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
2026 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
2027 // ROUTING POLICY: Send the same routing policy to both the hosts
2028 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
2029 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
2030 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
2031 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
2033 String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
2034 STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
2035 if(STR_LANGUAGE_CONTROLLER == null)
2036 throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
2037 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
2038 String strSSHCommand = null;
2039 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2040 strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
2041 else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
2042 strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
2044 throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
2045 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
2046 createThread(strSSHCommand);
2047 // Wait for connection
2048 // Create a new socket for communication
2049 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
2050 Socket socket = serverSocket.accept();
2051 InputStream inStream = null;
2052 OutputStream outStream = null;
2053 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2054 inStream = new ObjectInputStream(socket.getInputStream());
2055 outStream = new ObjectOutputStream(socket.getOutputStream());
2056 } else { // At this point the language is certainly C++, otherwise would've complained above
2057 inStream = new BufferedInputStream(socket.getInputStream());
2058 outStream = new BufferedOutputStream(socket.getOutputStream());
2061 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
2064 result = System.currentTimeMillis()-start;
2065 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
2067 start = System.currentTimeMillis();
2069 // Send files for every controller class
2070 // e.g. AcmeProximity.jar and AcmeProximity.zip
2071 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
2072 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
2073 strControllerClassName;
2075 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2076 sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
2077 // Create main controller/device object
2078 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
2079 "Create main object!", inStream, outStream);
2081 String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT;
2082 String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/";
2083 sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
2084 createMainObjectCpp(strObjControllerName, outStream, inStream);
2086 // Write basic MAC policies for controller
2087 //String strFileName = STR_MAC_POL_PATH + strObjControllerName + STR_MAC_POLICY_EXT;
2088 if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
2089 String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT;
2090 processJailConfig.configureProcessJailControllerPolicies(strObjControllerName, strFileName,
2091 strIoTMasterHostAdd, commHan.getComPort(strObjControllerName));
2092 // Whether or not we need additional Tomoyo policy?
2093 String strAddMACPolicy = parseConfigFile(strControllerCfg, STR_ADD_MAC_POL);
2094 if (strAddMACPolicy != null && strAddMACPolicy.equals("Yes")) {
2095 String strContMACCfg = STR_CONT_PATH + strObjControllerName + "/";
2096 processJailConfig.combineAdditionalMACPolicy(strContMACCfg, strObjControllerName, strObjControllerName);
2100 result = System.currentTimeMillis()-start;
2101 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
2102 System.out.println(" ==> Including file transfer times!\n\n");
2104 start = System.currentTimeMillis();
2106 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
2107 // Instrumenting one file
2108 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
2109 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
2110 HashMap<String,Object> hmControllerFieldObjects = null;
2111 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2112 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
2113 ClassReader cr = new ClassReader(fis);
2114 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
2115 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
2118 hmControllerFieldObjects = crim.getFieldObjects();
2120 String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
2121 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE);
2122 hmControllerFieldObjects = crim.getFieldObjects();
2124 // Get the object and the class names
2125 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
2126 //HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
2127 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
2128 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
2129 // Iterate over HashMap and choose between processing
2130 // SetInstrumenter vs. RelationInstrumenter
2131 String strFieldName = map.getKey();
2132 String strClassName = map.getValue().getClass().getName();
2134 System.out.println("\n\nDEBUG: Instrumenting IoTSet and IoTRelation objects!!!");
2135 System.out.println("DEBUG: Field name: " + strFieldName);
2136 System.out.println("DEBUG: Class name: " + strFieldName + "\n\n");
2138 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
2139 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
2140 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
2141 String strErrMsg = "IoTMaster: Controller object" +
2142 " cannot have IoTSet<IoTDeviceAddress>!";
2143 throw new Error(strErrMsg);
2144 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
2145 String strErrMsg = "IoTMaster: Controller object" +
2146 " cannot have IoTSet<ZigbeeAddress>!";
2147 throw new Error(strErrMsg);
2148 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
2149 // Instrument the IoTAddress
2150 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd, strObjControllerName);
2151 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
2154 instrumentIoTSet(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER);
2156 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
2157 instrumentIoTRelation(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER);
2160 // Combine controller MAC policies with the main policy file for the host
2161 String strTempFileName = "./" + strObjControllerName + STR_MAC_POLICY_EXT;
2162 processJailConfig.combineControllerMACPolicies(strIoTSlaveControllerHostAdd, strObjControllerName, strTempFileName);
2163 processJailConfig.flush();
2166 result = System.currentTimeMillis()-start;
2167 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
2168 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
2171 start = System.currentTimeMillis();
2173 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
2174 for(String s: commHan.getHosts()) {
2175 setHostBasicPolicies(s);
2177 // We retain all the basic policies for router,
2178 // but we delete the initial allowance policies for internal all TCP and UDP communications
2179 setRouterBasicPolicies(STR_ROUTER_ADD);
2180 routerConfig.closeMain();
2181 // Deploy the policy
2182 setAddresses = new HashSet<String>(commHan.getHosts());
2183 setAddresses.add(strIoTMasterHostAdd);
2184 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
2187 result = System.currentTimeMillis()-start;
2188 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
2191 start = System.currentTimeMillis();
2193 // Separating object creations and Set/Relation initializations
2194 createDriverObjects();
2197 result = System.currentTimeMillis()-start;
2198 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
2200 start = System.currentTimeMillis();
2202 // Sets and relations initializations
2203 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2204 initializeSetsAndRelationsJava(inStream, outStream);
2206 initializeSetsAndRelationsCpp(inStream, outStream);;
2209 result = System.currentTimeMillis()-start;
2210 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
2212 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2213 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
2214 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
2216 invokeInitMethodCpp(outStream, inStream);
2217 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
2218 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2219 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
2220 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
2221 } else // C++ side will wait until the program finishes, it's not generating a separate thread for now
2222 //endSessionCpp(outStream);
2226 serverSocket.close();
2227 objInitHand.clearObjectInitHandler();
2228 commHan.printLists();
2229 commHan.clearCommunicationHandler();
2230 lbIoT.printHostInfo();
2232 // Close access to policy files and deploy policies
2233 routerConfig.close();
2234 processJailConfig.close();
2235 if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
2236 createMACPolicyThreads(setAddresses);
2238 } catch (IOException |
2239 InterruptedException |
2240 ClassNotFoundException ex) {
2241 System.out.println("IoTMaster: Exception: "
2243 ex.printStackTrace();
2247 public static void main(String args[]) {
2249 // Detect the available controller/device classes
2250 // Input args[] should be used to list the controllers/devices
2251 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
2252 IoTMaster iotMaster = new IoTMaster(args);
2254 iotMaster.parseIoTMasterConfigFile();
2255 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
2256 iotMaster.initLiveDataStructure();
2258 iotMaster.createObjects();