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 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 ObjectInitHandler objInitHand;
55 private ObjectAddressInitHandler objAddInitHand;
56 private String[] strObjectNames;
57 // Now this can be either ClassRuntimeInstrumenterMaster or CRuntimeInstrumenterMaster
58 private Map<String,Object> mapClassNameToCrim;
61 * These properties hold information of a certain object
64 private String strObjName;
65 private String strObjClassName;
66 private String strObjClassInterfaceName;
67 private String strObjStubClsIntfaceName;
68 private String strIoTMasterHostAdd;
69 private String strIoTSlaveControllerHostAdd;
70 private String strIoTSlaveObjectHostAdd;
71 private Class[] arrFieldClasses;
72 private Object[] arrFieldValues;
73 private Socket filesocket;
76 * For connection with C++ IoTSlave
78 private ServerSocket serverSocketCpp;
79 private Socket socketCpp;
80 private BufferedInputStream inputCpp;
81 private BufferedOutputStream outputCpp;
83 // Constants that are to be extracted from config file
84 private static String STR_MASTER_MAC_ADD;
85 private static String STR_IOT_CODE_PATH;
86 private static String STR_CONT_PATH;
87 private static String STR_RUNTIME_DIR;
88 private static String STR_SLAVE_DIR;
89 private static String STR_CLS_PATH;
90 private static String STR_RMI_PATH;
91 private static String STR_RMI_HOSTNAME;
92 private static String STR_LOG_FILE_PATH;
93 private static String STR_USERNAME;
94 private static String STR_ROUTER_ADD;
95 private static String STR_MONITORING_HOST;
96 private static String STR_ZB_GATEWAY_ADDRESS;
97 private static String STR_ZB_GATEWAY_PORT;
98 private static String STR_ZB_IOTMASTER_PORT;
99 private static String STR_NUM_CALLBACK_PORTS;
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 boolean BOOL_VERBOSE;
108 * IoTMaster class constants
110 * Name constants - not to be configured by users
112 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
113 private static final String STR_CFG_FILE_EXT = ".config";
114 private static final String STR_CLS_FILE_EXT = ".class";
115 private static final String STR_JAR_FILE_EXT = ".jar";
116 private static final String STR_SO_FILE_EXT = ".so";
117 private static final String STR_ZIP_FILE_EXT = ".zip";
118 private static final String STR_TCP_PROTOCOL = "tcp";
119 private static final String STR_UDP_PROTOCOL = "udp";
120 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
121 private static final String STR_NO_PROTOCOL = "nopro";
122 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
123 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
124 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
125 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
126 private static final String STR_LANGUAGE = "LANGUAGE";
127 private static final String STR_YES = "Yes";
128 private static final String STR_NO = "No";
129 private static final String STR_JAVA = "Java";
130 private static final String STR_CPP = "C++";
131 private static final String STR_SSH = "ssh";
132 private static final String STR_SCP = "scp";
133 private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
135 private static int INT_SIZE = 4; // send length in the size of integer (4 bytes)
138 * Runtime class name constants - not to be configured by users
140 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
141 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
142 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
143 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
144 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
145 private static final String STR_IOT_ADD_CLS = "IoTAddress";
151 public IoTMaster(String[] argObjNms) {
157 objAddInitHand = null;
158 strObjectNames = argObjNms;
160 strObjClassName = null;
161 strObjClassInterfaceName = null;
162 strObjStubClsIntfaceName = null;
163 strIoTMasterHostAdd = null;
164 strIoTSlaveControllerHostAdd = null;
165 strIoTSlaveObjectHostAdd = null;
166 arrFieldClasses = null;
167 arrFieldValues = null;
169 mapClassNameToCrim = null;
170 // Connection with C++ IoTSlave
171 serverSocketCpp = null;
176 STR_MASTER_MAC_ADD = null;
177 STR_IOT_CODE_PATH = null;
178 STR_CONT_PATH = null;
179 STR_RUNTIME_DIR = null;
180 STR_SLAVE_DIR = null;
183 STR_RMI_HOSTNAME = null;
184 STR_LOG_FILE_PATH = null;
186 STR_ROUTER_ADD = null;
187 STR_MONITORING_HOST = null;
188 STR_ZB_GATEWAY_ADDRESS = null;
189 STR_ZB_GATEWAY_PORT = null;
190 STR_ZB_IOTMASTER_PORT = null;
191 STR_NUM_CALLBACK_PORTS = null;
192 STR_JVM_INIT_HEAP_SIZE = null;
193 STR_JVM_MAX_HEAP_SIZE = null;
194 STR_LANGUAGE_CONTROLLER = null;
195 BOOL_VERBOSE = false;
199 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
203 private void initLiveDataStructure() {
205 commHan = new CommunicationHandler(BOOL_VERBOSE);
206 lbIoT = new LoadBalancer(BOOL_VERBOSE);
207 lbIoT.setupLoadBalancer();
208 routerConfig = new RouterConfig();
209 routerConfig.getAddressList(STR_ROUTER_ADD);
210 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
211 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
212 mapClassNameToCrim = new HashMap<String,Object>();
216 * A method to initialize constants from config file
220 private void parseIoTMasterConfigFile() {
221 // Parse configuration file
222 Properties prop = new Properties();
223 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
224 File file = new File(strCfgFileName);
225 FileInputStream fis = null;
227 fis = new FileInputStream(file);
230 } catch (IOException ex) {
231 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
232 ex.printStackTrace();
234 // Initialize constants from config file
235 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
236 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
237 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
238 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
239 STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR");
240 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
241 STR_RMI_PATH = prop.getProperty("RMI_PATH");
242 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
243 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
244 STR_USERNAME = prop.getProperty("USERNAME");
245 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
246 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
247 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
248 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
249 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
250 STR_NUM_CALLBACK_PORTS = prop.getProperty("NUMBER_CALLBACK_PORTS");
251 STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
252 STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
253 //STR_LANGUAGE = prop.getProperty("LANGUAGE");
254 STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
255 STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
256 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
260 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
261 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
262 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
263 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
264 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
265 RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE);
266 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
267 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
268 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
269 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
270 RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE);
271 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
272 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
273 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
274 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
275 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
276 RuntimeOutput.print("STR_NUM_CALLBACK_PORTS=" + STR_NUM_CALLBACK_PORTS, BOOL_VERBOSE);
277 RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
278 RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
279 //RuntimeOutput.print("STR_LANGUAGE=" + STR_LANGUAGE, BOOL_VERBOSE);
280 RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
281 RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
282 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
283 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
287 * A method to parse information from a config file
289 * @param strCfgFileName Config file name
290 * @param strCfgField Config file field name
293 private String parseConfigFile(String strCfgFileName, String strCfgField) {
294 // Parse configuration file
295 Properties prop = new Properties();
296 File file = new File(strCfgFileName);
297 FileInputStream fis = null;
299 fis = new FileInputStream(file);
302 } catch (IOException ex) {
303 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
304 ex.printStackTrace();
306 System.out.println("IoTMaster: Reading " + strCfgField +
307 " from config file: " + strCfgFileName + " with value: " +
308 prop.getProperty(strCfgField, null));
309 // NULL is returned if the property isn't found
310 return prop.getProperty(strCfgField, null);
314 * A method to send files from IoTMaster
316 * @param filesocket File socket object
317 * @param sFileName File name
318 * @param lFLength File length
321 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
323 File file = new File(sFileName);
324 byte[] bytFile = new byte[toIntExact(lFLength)];
325 InputStream inFileStream = new FileInputStream(file);
327 OutputStream outFileStream = filesocket.getOutputStream();
329 while ((iCount = inFileStream.read(bytFile)) > 0) {
330 outFileStream.write(bytFile, 0, iCount);
333 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
337 * A method to create a thread
339 * @param sSSHCmd SSH command
342 private void createThread(String sSSHCmd) throws IOException {
344 // Start a new thread to start a new JVM
346 Runtime runtime = Runtime.getRuntime();
347 Process process = runtime.exec(sSSHCmd);
349 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
353 * A method to send command from master and receive reply from slave
355 * @params msgSend Message object
356 * @params strPurpose String that prints purpose message
357 * @params inStream Input stream
358 * @params outStream Output stream
361 private void commMasterToSlave(Message msgSend, String strPurpose,
362 InputStream _inStream, OutputStream _outStream)
363 throws IOException, ClassNotFoundException {
365 // Send message/command from master
366 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
367 outStream.writeObject(msgSend);
368 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
370 // Get reply from slave as acknowledgment
371 ObjectInputStream inStream = (ObjectInputStream) _inStream;
372 Message msgReply = (Message) inStream.readObject();
373 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
377 * A private method to instrument IoTSet device
379 * @params strFieldIdentifier String field name + object ID
380 * @params strFieldName String field name
381 * @params strIoTSlaveObjectHostAdd String slave host address
382 * @params inStream ObjectInputStream communication
383 * @params inStream ObjectOutputStream communication
384 * @params strLanguage String language
387 private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
388 InputStream inStream, OutputStream outStream, String strLanguage)
389 throws IOException, ClassNotFoundException, InterruptedException {
391 // Get information from the set
392 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
393 // Create a new IoTSet
394 if(strLanguage.equals(STR_JAVA)) {
395 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
396 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
398 createNewIoTSetCpp(strFieldName, outStream, inStream);
399 int iRows = listObject.size();
400 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
401 // Transfer the address
402 for(int iRow=0; iRow<iRows; iRow++) {
403 arrFieldValues = listObject.get(iRow);
404 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
405 String strDeviceAddress = null;
406 String strDeviceAddressKey = null;
407 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
408 strDeviceAddress = strIoTSlaveObjectHostAdd;
409 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
411 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
412 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
414 int iDestDeviceDriverPort = (int) arrFieldValues[1];
415 String strProtocol = (String) arrFieldValues[2];
416 // Check for wildcard feature
417 boolean bSrcPortWildCard = false;
418 boolean bDstPortWildCard = false;
419 if (arrFieldValues.length > 3) {
420 bSrcPortWildCard = (boolean) arrFieldValues[3];
421 bDstPortWildCard = (boolean) arrFieldValues[4];
423 // Add the port connection into communication handler - if it's not assigned yet
424 if (commHan.getComPort(strDeviceAddressKey) == null) {
425 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
429 System.out.println("\n\n DEBUG: InstrumentSetDevice: Object Name: " + strObjName);
430 System.out.println("DEBUG: InstrumentSetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
431 System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n");
433 // Send address one by one
434 if(strLanguage.equals(STR_JAVA)) {
435 Message msgGetIoTSetObj = null;
436 if (bDstPortWildCard) {
437 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
438 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
439 strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
441 msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
442 strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
443 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
445 getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort,
446 bSrcPortWildCard, bDstPortWildCard);
448 // Reinitialize IoTSet on device object
449 if(strLanguage.equals(STR_JAVA))
450 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
452 reinitializeIoTSetFieldCpp(outStream, inStream);
457 * A private method to instrument IoTSet Zigbee device
459 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
460 * @params strFieldName String field name
461 * @params strIoTSlaveObjectHostAdd String slave host address
462 * @params inStream ObjectInputStream communication
463 * @params inStream ObjectOutputStream communication
464 * @params strLanguage String language
467 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
468 InputStream inStream, OutputStream outStream, String strLanguage)
469 throws IOException, ClassNotFoundException, InterruptedException {
471 // Get information from the set
472 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
473 // Create a new IoTSet
474 if(strLanguage.equals(STR_JAVA)) {
475 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
476 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
477 } else // TODO: will need to implement IoTSet Zigbee for C++ later
479 // Prepare ZigbeeConfig
480 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
481 String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress;
482 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
483 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
484 commHan.addDevicePort(iZigbeeIoTMasterPort);
485 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
487 // Add the port connection into communication handler - if it's not assigned yet
488 if (commHan.getComPort(strZigbeeGWAddressKey) == null) {
489 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey);
491 int iRows = setInstrumenter.numberOfRows();
492 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
495 System.out.println("\n\n DEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
496 System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey));
497 System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n");
499 // Transfer the address
500 for(int iRow=0; iRow<iRows; iRow++) {
501 arrFieldValues = setInstrumenter.fieldValues(iRow);
502 // Get device address
503 String strZBDevAddress = (String) arrFieldValues[0];
504 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
505 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
506 // Send address one by one
507 if(strLanguage.equals(STR_JAVA)) {
508 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
509 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
510 } else // TODO: Implement IoTSet Zigbee for C++
513 zbConfig.closeConnection();
514 // Reinitialize IoTSet on device object
515 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
520 * A private method to instrument IoTSet of addresses
522 * @params strFieldIdentifier String field name + object ID
523 * @params strFieldName String field name
524 * @params inStream ObjectInputStream communication
525 * @params inStream ObjectOutputStream communication
526 * @params strLanguage String language
529 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
530 InputStream inStream, OutputStream outStream, String strLanguage)
531 throws IOException, ClassNotFoundException, InterruptedException {
533 // Get information from the set
534 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
535 // Create a new IoTSet
536 if(strLanguage.equals(STR_JAVA)) {
537 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
538 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
541 int iRows = listObject.size();
542 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
543 // Transfer the address
544 for(int iRow=0; iRow<iRows; iRow++) {
545 arrFieldValues = listObject.get(iRow);
546 // Get device address
547 String strAddress = (String) arrFieldValues[0];
548 // Send address one by one
549 if(strLanguage.equals(STR_JAVA)) {
550 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
551 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
552 } else // TODO: Implement IoTSet Address for C++
555 // Reinitialize IoTSet on device object
556 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
557 "Reinitialize IoTSet fields!", inStream, outStream);
562 * A private method to instrument an object on a specific machine and setting up policies
564 * @params strFieldObjectID String field object ID
565 * @params strLanguage String language
568 private void instrumentObject(String strFieldObjectID, String strLanguage) throws IOException {
570 // Extract the interface name for RMI
571 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
573 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
574 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
575 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
576 // Create an object name, e.g. ProximitySensorImplPS1
577 strObjName = strObjClassName + strFieldObjectID;
578 // Check first if host exists
579 if(commHan.objectExists(strObjName)) {
580 // If this object exists already ...
581 // Re-read IoTSlave object hostname for further reference
582 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
583 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
585 // If this is a new object ... then create one
586 // Get host address for IoTSlave from LoadBalancer
587 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
588 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
589 if (strIoTSlaveControllerHostAdd == null)
590 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
591 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
592 // Add port connection and get port numbers
593 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
594 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
595 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
596 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
597 // ROUTING POLICY: IoTMaster and device/controller object
598 // Master-slave communication
599 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
600 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
601 // ROUTING POLICY: Send the same routing policy to both the hosts
602 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
603 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
604 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
605 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
606 // Need to accommodate callback functions here - open ports for TCP
607 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
608 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
609 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
610 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
611 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
612 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
613 // Instrument the IoTSet declarations inside the class file
614 instrumentObjectIoTSet(strFieldObjectID, strLanguage);
616 // Send routing policy to router for controller object
617 // ROUTING POLICY: RMI communication - RMI registry and stub ports
618 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
619 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
620 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
621 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
622 // Send the same set of routing policies to compute nodes
623 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
624 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
625 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
626 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
627 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
628 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
629 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
630 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
631 // Send the same set of routing policies for callback ports
632 setCallbackPortsPolicy(strObjName, STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
636 * A private method to set router policies for callback ports
638 * @params strRouterAdd String router address
639 * @params strIoTSlaveControllerHostAdd String slave controller host address
640 * @params strIoTSlaveObjectHostAdd String slave object host address
641 * @params strProtocol String protocol
642 * @return iPort Integer port number
644 private void setCallbackPortsPolicy(String strObjName, String strRouterAdd, String strIoTSlaveControllerHostAdd,
645 String strIoTSlaveObjectHostAdd, String strProtocol) {
647 int iNumCallbackPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
648 Integer[] rmiCallbackPorts = commHan.getCallbackPorts(strObjName, iNumCallbackPorts);
650 // Iterate over port numbers and set up policies
651 for (int i=0; i<iNumCallbackPorts; i++) {
652 routerConfig.configureRouterMainPolicies(strRouterAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
653 strProtocol, rmiCallbackPorts[i]);
654 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
655 strProtocol, rmiCallbackPorts[i]);
656 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
657 strProtocol, rmiCallbackPorts[i]);
662 * A private method to set router policies for IoTDeviceAddress objects
664 * @params strFieldIdentifier String field name + object ID
665 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
666 * @params strIoTSlaveObjectHostAdd String slave host address
669 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
670 String strIoTSlaveObjectHostAdd) {
672 // Get information from the set
673 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
674 int iRows = setInstrumenter.numberOfRows();
675 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
676 // Transfer the address
677 for(int iRow=0; iRow<iRows; iRow++) {
678 arrFieldValues = setInstrumenter.fieldValues(iRow);
679 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
680 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
681 String strDeviceAddress = null;
682 String strDeviceAddressKey = null;
683 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
684 strDeviceAddress = strIoTSlaveObjectHostAdd;
685 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
686 } else { // Concatenate object name and IP address to give unique key - for a case where there is one device for multiple drivers
687 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
688 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
690 int iDestDeviceDriverPort = (int) arrFieldValues[1];
691 String strProtocol = (String) arrFieldValues[2];
692 // Add the port connection into communication handler - if it's not assigned yet
693 if (commHan.getComPort(strDeviceAddressKey) == null)
694 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
695 boolean bDstPortWildCard = false;
696 // Recognize this and allocate different ports for it
697 if (arrFieldValues.length > 3) {
698 bDstPortWildCard = (boolean) arrFieldValues[4];
699 if (bDstPortWildCard) { // This needs a unique source port
700 String strUniqueDev = strDeviceAddressKey + ":" + iRow;
701 commHan.addAdditionalPort(strUniqueDev);
706 System.out.println("\n\n DEBUG: InstrumentPolicySetDevice: Object Name: " + strObjName);
707 System.out.println("DEBUG: InstrumentPolicySetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
708 System.out.println("DEBUG: InstrumentPolicySetDevice: Device address: " + strDeviceAddressKey + "\n\n");
710 // Send routing policy to router for device drivers and devices
711 // ROUTING POLICY: RMI communication - RMI registry and stub ports
712 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
713 // Port number -1 means that we don't set the policy strictly to port number level
714 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
715 // ROUTING POLICY: Device driver and device
716 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
717 // ROUTING POLICY: Send to the compute node where the device driver is
718 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
719 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
720 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
721 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
722 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
723 // This is a TCP protocol that connects, e.g. a phone to our runtime system
724 // that provides a gateway access (accessed through destination port number)
725 commHan.addDevicePort(iDestDeviceDriverPort);
726 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
727 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
728 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
729 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
731 // Other port numbers...
732 commHan.addDevicePort(iDestDeviceDriverPort);
733 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
734 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
735 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol,
736 commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
742 * A private method to set router policies for IoTAddress objects
744 * @params strFieldIdentifier String field name + object ID
745 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
746 * @params strHostAddress String host address
749 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
750 String strHostAddress) {
752 // Get information from the set
753 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
754 int iRows = setInstrumenter.numberOfRows();
755 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
756 // Transfer the address
757 for(int iRow=0; iRow<iRows; iRow++) {
758 arrFieldValues = setInstrumenter.fieldValues(iRow);
759 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
760 // Get device address
761 String strAddress = (String) arrFieldValues[0];
762 // Setting up router policies for HTTP/HTTPs
763 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
764 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
769 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
771 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
773 * @params strFieldObjectID String field object ID
774 * @params strLanguage String language
777 private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
779 // If this is a new object ... then create one
780 // Instrument the class source code and look for IoTSet for device addresses
781 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
782 HashMap<String,Object> hmObjectFieldObjects = null;
783 if(strLanguage.equals(STR_JAVA)) {
784 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
785 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
786 ClassReader cr = new ClassReader(fis);
787 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
788 // We need Object ID to instrument IoTDeviceAddress
789 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
792 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
793 hmObjectFieldObjects = crim.getFieldObjects();
795 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
796 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE);
797 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
798 hmObjectFieldObjects = crim.getFieldObjects();
800 // Get the object and the class names
801 // Build objects for IoTSet and IoTRelation fields in the device object classes
802 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
803 strFieldObjectID, BOOL_VERBOSE);
804 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
805 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
806 // Iterate over HashMap and choose between processing
807 String strFieldName = map.getKey();
808 String strClassName = map.getValue().getClass().getName();
809 String strFieldIdentifier = strFieldName + strFieldObjectID;
810 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
811 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
812 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
813 // Instrument the normal IoTDeviceAddress
814 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
815 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
816 // Instrument the IoTAddress
817 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
818 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
819 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
820 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
823 String strErrMsg = "IoTMaster: Device driver object" +
824 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
825 " or IoTSet<IoTZigbeeAddress>!";
826 throw new Error(strErrMsg);
829 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
830 throw new Error(strErrMsg);
837 * A private method to send files to a Java slave driver
839 * @params serverSocket ServerSocket
840 * @params _inStream InputStream
841 * @params _outStream OutputStream
842 * @params strObjName String
843 * @params strObjClassName String
844 * @params strObjClassInterfaceName String
845 * @params strObjStubClsIntfaceName String
846 * @params strIoTSlaveObjectHostAdd String
847 * @params strFieldObjectID String
848 * @params arrFieldValues Object[]
849 * @params arrFieldClasses Class[]
852 private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream,
853 String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
854 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
855 throws IOException, ClassNotFoundException {
857 ObjectInputStream inStream = (ObjectInputStream) _inStream;
858 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
859 // Create message to transfer file first
860 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
861 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
862 File file = new File(sPath);
863 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
864 "Sending file!", inStream, outStream);
865 // Send file - JAR file for object creation
866 sendFile(serverSocket.accept(), sPath, file.length());
867 Message msgReply = (Message) inStream.readObject();
868 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
869 // Pack object information to create object on a IoTSlave
870 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
871 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
872 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
874 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
879 * A private method to send files to a Java slave driver
883 private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd)
884 throws IOException, ClassNotFoundException {
886 // Create message to transfer file first
887 String sFileName = strObjClassName + STR_ZIP_FILE_EXT;
888 String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
889 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR;
890 runCommand(strCmdSend);
891 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
893 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
894 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
895 runCommand(strCmdUnzip);
896 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
902 * Construct command line for Java IoTSlave
906 private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
908 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
909 STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
910 strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
911 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
912 commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
917 * Construct command line for C++ IoTSlave
921 private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
923 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
924 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
925 commHan.getComPort(strObjName) + " " + strObjName;
930 * A private method to create an object on a specific machine
932 * @params strObjName String object name
933 * @params strObjClassName String object class name
934 * @params strObjClassInterfaceName String object class interface name
935 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
936 * @params strFieldObjectID String field object ID
937 * @params arrFieldValues Array of field values
938 * @params arrFieldClasses Array of field classes
941 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
942 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
943 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
946 String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
947 String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
948 if(strLanguageDriver == null) // Read just the field LANGUAGE if the first read is null
949 strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
950 if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
951 throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
956 start = System.currentTimeMillis();
958 // Construct ssh command line
959 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
960 // java -cp $CLASSPATH:./*.jar
961 // -Djava.rmi.server.codebase=file:./*.jar
962 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
963 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
964 String strSSHCommand = null;
965 if(strLanguageDriver.equals(STR_JAVA))
966 strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
967 else if(strLanguageDriver.equals(STR_CPP))
968 strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
970 throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
971 RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
973 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
974 // Start a new thread to start a new JVM
975 createThread(strSSHCommand);
976 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
977 Socket socket = serverSocket.accept();
978 //InputStream inStream = new ObjectInputStream(socket.getInputStream());
979 //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
980 InputStream inStream = null;
981 OutputStream outStream = null;
982 if(strLanguageDriver.equals(STR_JAVA)) {
983 inStream = new ObjectInputStream(socket.getInputStream());
984 outStream = new ObjectOutputStream(socket.getOutputStream());
985 } else { // At this point the language is certainly C++, otherwise would've complained above
986 inStream = new BufferedInputStream(socket.getInputStream());
987 outStream = new BufferedOutputStream(socket.getOutputStream());
992 result = System.currentTimeMillis()-start;
993 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
996 start = System.currentTimeMillis();
998 if(strLanguageDriver.equals(STR_JAVA)) {
999 sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName,
1000 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1001 strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
1003 sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd);
1004 createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd,
1005 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses,
1006 outStream, inStream);
1010 result = System.currentTimeMillis()-start;
1011 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
1014 start = System.currentTimeMillis();
1016 // Instrument the class source code and look for IoTSet for device addresses
1017 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
1018 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE);
1019 // Get the object and the class names
1020 // Build objects for IoTSet and IoTRelation fields in the device object classes
1021 Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
1022 HashMap<String,Object> hmObjectFieldObjects = null;
1023 if (crimObj instanceof ClassRuntimeInstrumenterMaster) {
1024 ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj;
1025 hmObjectFieldObjects = crim.getFieldObjects();
1026 } else if (crimObj instanceof CRuntimeInstrumenterMaster) {
1027 CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj;
1028 hmObjectFieldObjects = crim.getFieldObjects();
1030 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
1031 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1032 // Iterate over HashMap and choose between processing
1033 String strFieldName = map.getKey();
1034 String strClassName = map.getValue().getClass().getName();
1035 String strFieldIdentifier = strFieldName + strFieldObjectID;
1036 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1037 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1038 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1039 // Instrument the normal IoTDeviceAddress
1040 synchronized(this) {
1041 instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1043 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1044 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
1045 synchronized(this) {
1046 instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1048 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1049 // Instrument the IoTAddress
1050 synchronized(this) {
1051 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
1054 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
1055 " or IoTSet<IoTZigbeeAddress>!";
1056 throw new Error(strErrMsg);
1059 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
1060 throw new Error(strErrMsg);
1064 // TODO: Change this later
1065 if(strLanguageDriver.equals(STR_JAVA)) {
1066 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
1067 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1068 } else { // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
1069 createDriverObjectCpp(outStream, inStream);
1070 //endSessionCpp(outStream);
1074 result = System.currentTimeMillis()-start;
1075 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
1081 serverSocket.close();
1086 * A private method to create controller objects
1090 private void createDriverObjects() throws InterruptedException {
1092 // Create a list of threads
1093 List<Thread> threads = new ArrayList<Thread>();
1094 // Get the list of active controller objects and loop it
1095 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
1096 for(String strObjName : listActiveControllerObject) {
1098 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
1099 Thread objectThread = new Thread(new Runnable() {
1101 synchronized(this) {
1103 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
1104 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
1105 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
1106 commHan.getArrayFieldClasses(strObjName));
1107 } catch (IOException |
1108 ClassNotFoundException |
1109 InterruptedException ex) {
1110 ex.printStackTrace();
1115 threads.add(objectThread);
1116 objectThread.start();
1119 for (Thread thread : threads) {
1122 } catch (InterruptedException ex) {
1123 ex.printStackTrace();
1130 * A private method to instrument IoTSet
1132 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
1133 * @params strFieldName String field name
1134 * @params strLanguage String language
1137 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strLanguage)
1138 throws IOException, ClassNotFoundException, InterruptedException {
1140 // Get information from the set
1141 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1142 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
1144 int iRows = setInstrumenter.numberOfRows();
1145 for(int iRow=0; iRow<iRows; iRow++) {
1146 // Get field classes and values
1147 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
1148 arrFieldValues = setInstrumenter.fieldValues(iRow);
1149 // Get object ID and class name
1150 String strObjID = setInstrumenter.fieldObjectID(iRow);
1151 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
1152 // Call the method to create an object
1153 instrumentObject(strObjID, strLanguage);
1154 int iNumOfPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
1155 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1156 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
1157 commHan.getRMIStubPort(strObjName), commHan.getCallbackPorts(strObjName, iNumOfPorts));
1163 * A private method to instrument IoTRelation
1165 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
1166 * @params strFieldName String field name
1167 * @params strLanguage String language
1170 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strLanguage)
1171 throws IOException, ClassNotFoundException, InterruptedException {
1173 // Get information from the set
1174 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
1175 int iRows = relationInstrumenter.numberOfRows();
1176 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
1178 for(int iRow=0; iRow<iRows; iRow++) {
1179 // Operate on the first set first
1180 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
1181 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
1182 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
1183 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
1184 // Call the method to create an object
1185 instrumentObject(strObjID, strLanguage);
1186 // Get the first object controller host address
1187 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1188 int iNumOfPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
1189 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1190 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1191 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName),
1192 commHan.getCallbackPorts(strObjName, iNumOfPorts));
1193 // Operate on the second set
1194 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
1195 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
1196 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
1197 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
1198 // Call the method to create an object
1199 instrumentObject(strObjID, strLanguage);
1200 // Get the second object controller host address
1201 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1202 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1203 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1204 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName),
1205 commHan.getCallbackPorts(strObjName, iNumOfPorts));
1206 // ROUTING POLICY: first and second controller objects in IoTRelation
1207 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
1208 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1209 // ROUTING POLICY: Send the same routing policy to both the hosts
1210 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1211 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1212 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1213 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1218 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1220 * @params inStream ObjectInputStream communication
1221 * @params outStream ObjectOutputStream communication
1224 private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream)
1225 throws IOException, ClassNotFoundException {
1226 // Get list of fields
1227 List<String> strFields = objInitHand.getListOfFields();
1228 // Iterate on HostAddress
1229 for(String str : strFields) {
1230 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1231 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1232 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1233 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
1234 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1235 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1236 for (ObjectInitInfo objInitInfo : listObject) {
1237 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1238 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1239 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
1240 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(),
1241 objInitInfo.getRMICallbackPorts()), "Get IoTSet object!", inStream, outStream);
1244 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1245 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1246 "Renitialize IoTSet field!", inStream, outStream);
1247 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1248 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1249 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1250 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1251 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1252 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1253 Iterator it = listSecondObject.iterator();
1254 for (ObjectInitInfo objInitInfo : listObject) {
1255 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1256 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
1257 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1258 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1259 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), objInitInfo.getRMICallbackPorts()),
1260 "Get IoTRelation first object!", inStream, outStream);
1261 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1262 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1263 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1264 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1265 objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1266 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), objSecObj.getRMICallbackPorts()),
1267 "Get IoTRelation second object!", inStream, outStream);
1269 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1270 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1271 "Renitialize IoTRelation field!", inStream, outStream);
1277 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1279 * @params inStream ObjectInputStream communication
1280 * @params outStream ObjectOutputStream communication
1283 private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream)
1284 throws IOException, ClassNotFoundException {
1285 // Get list of fields
1286 List<String> strFields = objInitHand.getListOfFields();
1287 // Iterate on HostAddress
1288 for(String str : strFields) {
1289 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1290 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1291 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1292 createNewIoTSetCpp(str, outStream, inStream);
1293 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1294 for (ObjectInitInfo objInitInfo : listObject) {
1295 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1296 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1297 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1298 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), objInitInfo.getRMICallbackPorts(), outStream, inStream);
1300 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1301 reinitializeIoTSetFieldCpp(outStream, inStream);
1302 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1303 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1304 // TODO: createNewIoTRelation needs to be created here!
1305 createNewIoTRelationCpp(str, outStream, inStream);
1306 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1307 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1308 Iterator it = listSecondObject.iterator();
1309 for (ObjectInitInfo objInitInfo : listObject) {
1310 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1311 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(),
1312 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1313 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), objInitInfo.getRMICallbackPorts(), outStream, inStream);
1314 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1315 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1316 getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(),
1317 objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1318 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), objSecObj.getRMICallbackPorts(), outStream, inStream);
1320 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1321 reinitializeIoTRelationFieldCpp(outStream, inStream);
1327 * A method to set router basic policies at once
1329 * @param strRouter String router name
1332 private void setRouterBasicPolicies(String strRouter) {
1334 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1335 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1336 routerConfig.configureRouterDHCPPolicies(strRouter);
1337 routerConfig.configureRouterDNSPolicies(strRouter);
1338 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1339 routerConfig.configureRejectPolicies(strRouter);
1343 * A method to set host basic policies at once
1345 * @param strHost String host name
1348 private void setHostBasicPolicies(String strHost) {
1350 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1351 routerConfig.configureHostDHCPPolicies(strHost);
1352 routerConfig.configureHostDNSPolicies(strHost);
1353 if (strHost.equals(strMonitorHost)) {
1354 // Check if this is the monitoring host
1355 routerConfig.configureHostICMPPolicies(strHost);
1356 routerConfig.configureHostSSHPolicies(strHost);
1358 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1359 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1361 // Apply SQL allowance policies to master host
1362 if (strHost.equals(strIoTMasterHostAdd)) {
1363 routerConfig.configureHostSQLPolicies(strHost);
1365 routerConfig.configureRejectPolicies(strHost);
1369 * A method to create a thread for policy deployment
1371 * @param strRouterAddress String router address to configure
1372 * @param setHostAddresses Set of strings for host addresses to configure
1375 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1377 // Create a list of threads
1378 List<Thread> threads = new ArrayList<Thread>();
1379 // Start threads for hosts
1380 for(String strAddress : setHostAddresses) {
1381 Thread policyThread = new Thread(new Runnable() {
1383 synchronized(this) {
1384 routerConfig.sendHostPolicies(strAddress);
1388 threads.add(policyThread);
1389 policyThread.start();
1390 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1392 // A thread for router
1393 Thread policyThread = new Thread(new Runnable() {
1395 synchronized(this) {
1396 routerConfig.sendRouterPolicies(strRouterAddress);
1400 threads.add(policyThread);
1401 policyThread.start();
1402 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1404 for (Thread thread : threads) {
1407 } catch (InterruptedException ex) {
1408 ex.printStackTrace();
1415 * A method to send files to Java IoTSlave
1417 * @params strObjControllerName String
1418 * @params serverSocket ServerSocket
1419 * @params inStream ObjectInputStream communication
1420 * @params outStream ObjectOutputStream communication
1423 private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket,
1424 InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException {
1426 ObjectInputStream inStream = (ObjectInputStream) _inStream;
1427 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
1429 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1430 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1431 strControllerJarName;
1432 File file = new File(strControllerJarNamePath);
1433 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1434 "Sending file!", inStream, outStream);
1435 // Send file - Class file for object creation
1436 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1437 Message msgReply = (Message) inStream.readObject();
1438 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1439 // Send .zip file if additional zip file is specified
1440 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1441 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1442 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1443 if (strAdditionalFile.equals(STR_YES)) {
1444 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1445 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1446 strControllerCmpName;
1447 file = new File(strControllerCmpNamePath);
1448 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1449 "Sending file!", inStream, outStream);
1450 // Send file - Class file for object creation
1451 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1452 msgReply = (Message) inStream.readObject();
1453 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1459 * A method to send files to C++ IoTSlave
1462 * TODO: Need to look into this (as of now, file transferred retains the "data" format,
1463 * hence it is unreadable from outside world
1465 private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket,
1466 InputStream inStream, OutputStream outStream) throws IOException {
1468 sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream);
1470 sendString(sFileName, outStream); recvAck(inStream);
1471 File file = new File(sFilePath + sFileName);
1472 int iFileLen = toIntExact(file.length());
1473 RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
1475 sendInteger(iFileLen, outStream); recvAck(inStream);
1476 RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
1477 byte[] bytFile = new byte[iFileLen];
1478 InputStream inFileStream = new FileInputStream(file);
1479 RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
1481 OutputStream outFileStream = fileSocket.getOutputStream();
1482 RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
1484 while ((iCount = inFileStream.read(bytFile)) > 0) {
1485 outFileStream.write(bytFile, 0, iCount);
1487 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
1493 * A method to send files to C++ IoTSlave (now master using Process() to start
1494 * file transfer using scp)
1498 private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException {
1500 // Construct shell command to transfer file
1501 String sFile = sFilePath + sFileName;
1502 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR;
1503 runCommand(strCmdSend);
1504 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
1506 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1507 STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
1508 runCommand(strCmdUnzip);
1509 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
1514 * runCommand() method runs shell command
1516 * @param strCommand String that contains command line
1519 private void runCommand(String strCommand) {
1522 Runtime runtime = Runtime.getRuntime();
1523 Process process = runtime.exec(strCommand);
1525 } catch (IOException ex) {
1526 System.out.println("RouterConfig: IOException: " + ex.getMessage());
1527 ex.printStackTrace();
1528 } catch (InterruptedException ex) {
1529 System.out.println("RouterConfig: InterruptException: " + ex.getMessage());
1530 ex.printStackTrace();
1536 * Construct command line for Java IoTSlave
1540 private String getCmdJavaIoTSlave(String strObjControllerName) {
1542 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1543 STR_RUNTIME_DIR + " sudo java " + STR_JVM_INIT_HEAP_SIZE + " " +
1544 STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " +
1545 STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1546 commHan.getComPort(strObjControllerName) + " " +
1547 commHan.getRMIRegPort(strObjControllerName) + " " +
1548 commHan.getRMIStubPort(strObjControllerName) + " >& " +
1549 STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1554 * Construct command line for C++ IoTSlave
1558 private String getCmdCppIoTSlave(String strObjControllerName) {
1560 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1561 STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
1562 commHan.getComPort(strObjControllerName) + " " + strObjControllerName;
1567 * sendInteger() sends an integer in bytes
1569 public void sendInteger(int intSend, OutputStream outStream) throws IOException {
1571 BufferedOutputStream output = (BufferedOutputStream) outStream;
1572 // Transform integer into bytes
1573 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
1575 // Send the byte array
1576 output.write(bb.array(), 0, INT_SIZE);
1582 * recvInteger() receives integer in bytes
1584 public int recvInteger(InputStream inStream) throws IOException {
1586 BufferedInputStream input = (BufferedInputStream) inStream;
1587 // Wait until input is available
1588 while(input.available() == 0);
1589 // Read integer - 4 bytes
1590 byte[] recvInt = new byte[INT_SIZE];
1591 input.read(recvInt, 0, INT_SIZE);
1592 int retVal = ByteBuffer.wrap(recvInt).getInt();
1599 * recvString() receives String in bytes
1601 public String recvString(InputStream inStream) throws IOException {
1603 BufferedInputStream input = (BufferedInputStream) inStream;
1604 int strLen = recvInteger(inStream);
1605 // Wait until input is available
1606 while(input.available() == 0);
1607 // Read String per strLen
1608 byte[] recvStr = new byte[strLen];
1609 input.read(recvStr, 0, strLen);
1610 String retVal = new String(recvStr);
1617 * sendString() sends a String in bytes
1619 public void sendString(String strSend, OutputStream outStream) throws IOException {
1621 BufferedOutputStream output = (BufferedOutputStream) outStream;
1622 // Transform String into bytes
1623 byte[] strSendBytes = strSend.getBytes();
1624 int strLen = strSend.length();
1625 // Send the string length first
1626 sendInteger(strLen, outStream);
1627 // Send the byte array
1628 output.write(strSendBytes, 0, strLen);
1634 * Convert integer to enum
1636 public IoTCommCode getCode(int intCode) throws IOException {
1638 IoTCommCode[] commCode = IoTCommCode.values();
1639 IoTCommCode retCode = commCode[intCode];
1648 public synchronized boolean recvAck(InputStream inStream) throws IOException {
1650 int intAck = recvInteger(inStream);
1651 IoTCommCode codeAck = getCode(intAck);
1652 if (codeAck == IoTCommCode.ACKNOWLEDGED)
1662 public void sendEndTransfer(OutputStream outStream) throws IOException {
1664 int endCode = IoTCommCode.END_TRANSFER.ordinal();
1665 sendInteger(endCode, outStream);
1670 * Send communication code to C++
1672 public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException {
1675 IoTCommCode commCode = inpCommCode;
1676 int intCode = commCode.ordinal();
1677 // TODO: delete this later
1678 System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode);
1679 sendInteger(intCode, outStream); recvAck(inStream);
1684 * Create a main controller object for C++
1686 public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException {
1688 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
1689 String strMainObjName = strObjControllerName;
1690 sendString(strMainObjName, outStream); recvAck(inStream);
1691 RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
1696 * A helper function that converts Class into String
1698 * @param strDataType String MySQL data type
1701 public String getClassConverted(Class<?> cls) {
1703 if (cls == String.class) {
1705 } else if (cls == int.class) {
1714 * A helper function that converts Object into String for transfer to C++ slave
1716 * @param obj Object to be converted
1717 * @param strClassType String Java Class type
1720 public String getObjectConverted(Object obj) {
1722 if (obj instanceof String) {
1723 return (String) obj;
1724 } else if (obj instanceof Integer) {
1725 return Integer.toString((Integer) obj);
1733 * Create a driver object for C++
1735 public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd,
1736 Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses,
1737 OutputStream outStream, InputStream inStream) throws IOException {
1739 sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
1740 RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
1741 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
1742 sendString(strObjName, outStream); recvAck(inStream);
1743 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
1744 sendString(strObjClassName, outStream); recvAck(inStream);
1745 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
1746 sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
1747 RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
1748 sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
1749 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1750 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1751 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1752 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1753 int numOfArgs = arrFieldValues.length;
1754 RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
1755 sendInteger(numOfArgs, outStream); recvAck(inStream);
1756 for(Object obj : arrFieldValues) {
1757 String str = getObjectConverted(obj);
1758 sendString(str, outStream); recvAck(inStream);
1760 RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
1761 for(Class cls : arrFieldClasses) {
1762 String str = getClassConverted(cls);
1763 sendString(str, outStream); recvAck(inStream);
1769 * Create new IoTSet for C++
1771 public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1773 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
1774 RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
1775 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1776 sendString(strObjFieldName, outStream); recvAck(inStream);
1781 * Create new IoTRelation for C++
1783 public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1785 sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
1786 RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
1787 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1788 sendString(strObjFieldName, outStream); recvAck(inStream);
1793 * Get a IoTDeviceAddress object for C++
1795 public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream,
1796 String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
1798 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
1799 RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
1800 sendString(strDeviceAddress, outStream); recvAck(inStream);
1801 sendInteger(iSourcePort, outStream); recvAck(inStream);
1802 sendInteger(iDestPort, outStream); recvAck(inStream);
1803 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
1804 sendInteger(iSourceWildCard, outStream); recvAck(inStream);
1805 int iDestWildCard = (bDestWildCard ? 1 : 0);
1806 sendInteger(iDestWildCard, outStream); recvAck(inStream);
1807 RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
1812 * Get a IoTSet content object for C++
1814 public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName,
1815 String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort,
1816 Integer[] iCallbackPorts, OutputStream outStream, InputStream inStream) throws IOException {
1818 sendCommCode(iotCommCode, outStream, inStream);
1819 RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
1821 RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
1822 sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
1823 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
1824 sendString(strObjectName, outStream); recvAck(inStream);
1825 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
1826 sendString(strObjectClassName, outStream); recvAck(inStream);
1827 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
1828 sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
1829 RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
1830 sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
1831 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1832 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1833 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1834 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1835 sendInteger(iCallbackPorts.length, outStream); recvAck(inStream);
1836 for(Integer i : iCallbackPorts) {
1837 sendInteger(i, outStream); recvAck(inStream);
1843 * Reinitialize IoTRelation field for C++
1845 private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1847 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
1848 sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
1849 RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
1854 * Reinitialize IoTSet field for C++
1856 private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1858 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
1859 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
1860 RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
1865 * Create driver object for C++
1867 private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
1869 sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
1870 RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
1875 * Invoke init() for C++
1877 private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
1879 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
1880 RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
1885 * End session for C++
1887 public void endSessionCpp(OutputStream outStream) throws IOException {
1889 // Send message to end session
1890 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
1891 int intCode = endSessionCode.ordinal();
1892 sendInteger(intCode, outStream);
1893 //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
1894 RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
1899 * A method to assign objects to multiple JVMs, including
1900 * the controller/device object that uses other objects
1901 * in IoTSet and IoTRelation
1905 private void createObjects() {
1912 // Extract hostname for this IoTMaster from MySQL DB
1913 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1914 // Loop as we can still find controller/device classes
1915 for(int i=0; i<strObjectNames.length; i++) {
1917 start = System.currentTimeMillis();
1919 // Assign a new list of PrintWriter objects
1920 routerConfig.renewPrintWriter();
1921 // Get controller names one by one
1922 String strObjControllerName = strObjectNames[i];
1923 // Use LoadBalancer to assign a host address
1924 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1925 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1926 if (strIoTSlaveControllerHostAdd == null)
1927 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1928 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1929 // Add port connection and get port numbers
1930 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1931 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1932 // ROUTING POLICY: IoTMaster and main controller object
1933 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1934 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1935 // ROUTING POLICY: Send the same routing policy to both the hosts
1936 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1937 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1938 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1939 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1941 String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
1942 STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
1943 if(STR_LANGUAGE_CONTROLLER == null)
1944 throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
1945 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1946 String strSSHCommand = null;
1947 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
1948 strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
1949 else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
1950 strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
1952 throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
1953 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1954 createThread(strSSHCommand);
1955 // Wait for connection
1956 // Create a new socket for communication
1957 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1958 Socket socket = serverSocket.accept();
1959 InputStream inStream = null;
1960 OutputStream outStream = null;
1961 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1962 inStream = new ObjectInputStream(socket.getInputStream());
1963 outStream = new ObjectOutputStream(socket.getOutputStream());
1964 } else { // At this point the language is certainly C++, otherwise would've complained above
1965 inStream = new BufferedInputStream(socket.getInputStream());
1966 outStream = new BufferedOutputStream(socket.getOutputStream());
1969 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1972 result = System.currentTimeMillis()-start;
1973 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
1975 start = System.currentTimeMillis();
1977 // Send files for every controller class
1978 // e.g. AcmeProximity.jar and AcmeProximity.zip
1979 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
1980 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1981 strControllerClassName;
1983 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1984 sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
1985 // Create main controller/device object
1986 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
1987 "Create main object!", inStream, outStream);
1989 String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT;
1990 String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/";
1991 sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
1992 createMainObjectCpp(strObjControllerName, outStream, inStream);
1996 result = System.currentTimeMillis()-start;
1997 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
1998 System.out.println(" ==> Including file transfer times!\n\n");
2000 start = System.currentTimeMillis();
2002 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
2003 // Instrumenting one file
2004 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
2005 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
2006 HashMap<String,Object> hmControllerFieldObjects = null;
2007 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2008 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
2009 ClassReader cr = new ClassReader(fis);
2010 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
2011 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
2014 hmControllerFieldObjects = crim.getFieldObjects();
2016 String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
2017 CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE);
2018 hmControllerFieldObjects = crim.getFieldObjects();
2020 // Get the object and the class names
2021 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
2022 //HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
2023 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
2024 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
2025 // Iterate over HashMap and choose between processing
2026 // SetInstrumenter vs. RelationInstrumenter
2027 String strFieldName = map.getKey();
2028 String strClassName = map.getValue().getClass().getName();
2029 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
2030 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
2031 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
2032 String strErrMsg = "IoTMaster: Controller object" +
2033 " cannot have IoTSet<IoTDeviceAddress>!";
2034 throw new Error(strErrMsg);
2035 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
2036 String strErrMsg = "IoTMaster: Controller object" +
2037 " cannot have IoTSet<ZigbeeAddress>!";
2038 throw new Error(strErrMsg);
2039 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
2040 // Instrument the IoTAddress
2041 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
2042 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
2045 instrumentIoTSet(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2047 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
2048 instrumentIoTRelation(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2052 result = System.currentTimeMillis()-start;
2053 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
2054 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
2057 start = System.currentTimeMillis();
2059 // ROUTING POLICY: Deploy basic policies if this is the last controller
2060 if (i == strObjectNames.length-1) {
2061 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
2062 for(String s: commHan.getHosts()) {
2063 setHostBasicPolicies(s);
2065 // We retain all the basic policies for router,
2066 // but we delete the initial allowance policies for internal all TCP and UDP communications
2067 setRouterBasicPolicies(STR_ROUTER_ADD);
2069 // Close access to policy files and deploy policies
2070 routerConfig.close();
2071 // Deploy the policy
2072 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
2073 setAddresses.add(strIoTMasterHostAdd);
2074 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
2077 result = System.currentTimeMillis()-start;
2078 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
2081 start = System.currentTimeMillis();
2083 // Separating object creations and Set/Relation initializations
2084 createDriverObjects();
2087 result = System.currentTimeMillis()-start;
2088 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
2090 start = System.currentTimeMillis();
2092 // Sets and relations initializations
2093 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2094 initializeSetsAndRelationsJava(inStream, outStream);
2096 initializeSetsAndRelationsCpp(inStream, outStream);;
2099 result = System.currentTimeMillis()-start;
2100 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
2102 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2103 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
2104 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
2106 invokeInitMethodCpp(outStream, inStream);
2107 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
2108 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2109 ObjectOutputStream oStream = (ObjectOutputStream) outStream;
2110 oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
2111 } else // C++ side will wait until the program finishes, it's not generating a separate thread for now
2112 //endSessionCpp(outStream);
2116 serverSocket.close();
2117 commHan.printLists();
2118 lbIoT.printHostInfo();
2121 } catch (IOException |
2122 InterruptedException |
2123 ClassNotFoundException ex) {
2124 System.out.println("IoTMaster: Exception: "
2126 ex.printStackTrace();
2130 public static void main(String args[]) {
2132 // Detect the available controller/device classes
2133 // Input args[] should be used to list the controllers/devices
2134 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
2135 IoTMaster iotMaster = new IoTMaster(args);
2137 iotMaster.parseIoTMasterConfigFile();
2138 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
2139 iotMaster.initLiveDataStructure();
2141 iotMaster.createObjects();