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.ObjectInputStream;
23 import java.io.ObjectOutputStream;
24 import java.io.IOException;
25 import java.lang.ClassNotFoundException;
26 import java.lang.Class;
27 import java.lang.reflect.*;
28 import java.net.Socket;
29 import java.net.ServerSocket;
31 import static java.lang.Math.toIntExact;
33 /** Class IoTMaster is responsible to use ClassRuntimeInstrumenterMaster
34 * to instrument the controller/device bytecode and starts multiple
35 * IoTSlave running on different JVM's in a distributed fashion.
37 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
41 public class IoTMaster {
44 * IoTMaster class properties
46 * CommunicationHandler maintains the data structure for hostnames and ports
47 * LoadBalancer assigns a job onto a host based on certain metrics
49 private CommunicationHandler commHan;
50 private LoadBalancer lbIoT;
51 private RouterConfig routerConfig;
52 private ObjectInitHandler objInitHand;
53 private ObjectAddressInitHandler objAddInitHand;
54 private String[] strObjectNames;
55 private Map<String,ClassRuntimeInstrumenterMaster> mapClassNameToCrim;
57 * These properties hold information of a certain object
60 private String strObjName;
61 private String strObjClassName;
62 private String strObjClassInterfaceName;
63 private String strObjStubClsIntfaceName;
64 private String strIoTMasterHostAdd;
65 private String strIoTSlaveControllerHostAdd;
66 private String strIoTSlaveObjectHostAdd;
67 private Class[] arrFieldClasses;
68 private Object[] arrFieldValues;
69 private Socket filesocket;
71 // Constants that are to be extracted from config file
72 private static String STR_MASTER_MAC_ADD;
73 private static String STR_IOT_CODE_PATH;
74 private static String STR_CONT_PATH;
75 private static String STR_RUNTIME_DIR;
76 private static String STR_CLS_PATH;
77 private static String STR_RMI_PATH;
78 private static String STR_RMI_HOSTNAME;
79 private static String STR_LOG_FILE_PATH;
80 private static String STR_SSH_USERNAME;
81 private static String STR_ROUTER_ADD;
82 private static String STR_MONITORING_HOST;
83 private static String STR_ZB_GATEWAY_ADDRESS;
84 private static String STR_ZB_GATEWAY_PORT;
85 private static String STR_ZB_IOTMASTER_PORT;
86 private static String STR_NUM_CALLBACK_PORTS;
87 private static boolean BOOL_VERBOSE;
90 * IoTMaster class constants
92 * Name constants - not to be configured by users
94 private static final String STR_IOT_MASTER_NAME = "IoTMaster";
95 private static final String STR_CFG_FILE_EXT = ".config";
96 private static final String STR_CLS_FILE_EXT = ".class";
97 private static final String STR_JAR_FILE_EXT = ".jar";
98 private static final String STR_ZIP_FILE_EXT = ".zip";
99 private static final String STR_TCP_PROTOCOL = "tcp";
100 private static final String STR_UDP_PROTOCOL = "udp";
101 private static final String STR_TCPGW_PROTOCOL = "tcpgw";
102 private static final String STR_NO_PROTOCOL = "nopro";
103 private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
104 private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
105 private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
106 private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
107 private static final String STR_YES = "Yes";
108 private static final String STR_NO = "No";
111 * Runtime class name constants - not to be configured by users
113 private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
114 private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
115 private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
116 private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
117 private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
118 private static final String STR_IOT_ADD_CLS = "IoTAddress";
124 public IoTMaster(String[] argObjNms) {
130 objAddInitHand = null;
131 strObjectNames = argObjNms;
133 strObjClassName = null;
134 strObjClassInterfaceName = null;
135 strObjStubClsIntfaceName = null;
136 strIoTMasterHostAdd = null;
137 strIoTSlaveControllerHostAdd = null;
138 strIoTSlaveObjectHostAdd = null;
139 arrFieldClasses = null;
140 arrFieldValues = null;
142 mapClassNameToCrim = null;
144 STR_MASTER_MAC_ADD = null;
145 STR_IOT_CODE_PATH = null;
146 STR_CONT_PATH = null;
147 STR_RUNTIME_DIR = null;
150 STR_RMI_HOSTNAME = null;
151 STR_LOG_FILE_PATH = null;
152 STR_SSH_USERNAME = null;
153 STR_ROUTER_ADD = null;
154 STR_MONITORING_HOST = null;
155 STR_ZB_GATEWAY_ADDRESS = null;
156 STR_ZB_GATEWAY_PORT = null;
157 STR_ZB_IOTMASTER_PORT = null;
158 STR_NUM_CALLBACK_PORTS = null;
159 BOOL_VERBOSE = false;
163 * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
167 private void initLiveDataStructure() {
169 commHan = new CommunicationHandler(BOOL_VERBOSE);
170 lbIoT = new LoadBalancer(BOOL_VERBOSE);
171 lbIoT.setupLoadBalancer();
172 routerConfig = new RouterConfig();
173 routerConfig.getAddressList(STR_ROUTER_ADD);
174 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
175 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
176 mapClassNameToCrim = new HashMap<String,ClassRuntimeInstrumenterMaster>();
180 * A method to initialize constants from config file
184 private void parseIoTMasterConfigFile() {
185 // Parse configuration file
186 Properties prop = new Properties();
187 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
188 File file = new File(strCfgFileName);
189 FileInputStream fis = null;
191 fis = new FileInputStream(file);
194 } catch (IOException ex) {
195 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
196 ex.printStackTrace();
198 // Initialize constants from config file
199 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
200 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
201 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
202 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
203 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
204 STR_RMI_PATH = prop.getProperty("RMI_PATH");
205 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
206 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
207 STR_SSH_USERNAME = prop.getProperty("SSH_USERNAME");
208 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
209 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
210 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
211 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
212 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
213 STR_NUM_CALLBACK_PORTS = prop.getProperty("NUMBER_CALLBACK_PORTS");
214 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
218 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
219 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
220 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
221 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
222 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
223 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
224 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
225 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
226 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
227 RuntimeOutput.print("STR_SSH_USERNAME=" + STR_SSH_USERNAME, BOOL_VERBOSE);
228 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
229 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
230 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
231 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
232 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
233 RuntimeOutput.print("STR_NUM_CALLBACK_PORTS=" + STR_NUM_CALLBACK_PORTS, BOOL_VERBOSE);
234 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
235 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
239 * A method to parse information from a config file
241 * @param strCfgFileName Config file name
242 * @param strCfgField Config file field name
245 private String parseConfigFile(String strCfgFileName, String strCfgField) {
246 // Parse configuration file
247 Properties prop = new Properties();
248 File file = new File(strCfgFileName);
249 FileInputStream fis = null;
251 fis = new FileInputStream(file);
254 } catch (IOException ex) {
255 System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
256 ex.printStackTrace();
258 System.out.println("IoTMaster: Reading " + strCfgField +
259 " from config file: " + strCfgFileName + " with value: " +
260 prop.getProperty(strCfgField, null));
261 // NULL is returned if the property isn't found
262 return prop.getProperty(strCfgField, null);
266 * A method to send files from IoTMaster
268 * @param filesocket File socket object
269 * @param sFileName File name
270 * @param lFLength File length
273 private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
275 File file = new File(sFileName);
276 byte[] bytFile = new byte[toIntExact(lFLength)];
277 InputStream inFileStream = new FileInputStream(file);
279 OutputStream outFileStream = filesocket.getOutputStream();
281 while ((iCount = inFileStream.read(bytFile)) > 0) {
282 outFileStream.write(bytFile, 0, iCount);
285 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
289 * A method to create a thread
291 * @param sSSHCmd SSH command
294 private void createThread(String sSSHCmd) throws IOException {
296 // Start a new thread to start a new JVM
298 Runtime runtime = Runtime.getRuntime();
299 Process process = runtime.exec(sSSHCmd);
301 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
305 * A method to send command from master and receive reply from slave
307 * @params msgSend Message object
308 * @params strPurpose String that prints purpose message
309 * @params inStream Input stream
310 * @params outStream Output stream
313 private void commMasterToSlave(Message msgSend, String strPurpose,
314 ObjectInputStream inStream, ObjectOutputStream outStream)
315 throws IOException, ClassNotFoundException {
317 // Send message/command from master
318 outStream.writeObject(msgSend);
319 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
321 // Get reply from slave as acknowledgment
322 Message msgReply = (Message) inStream.readObject();
323 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
327 * A private method to instrument IoTSet device
329 * @params strFieldIdentifier String field name + object ID
330 * @params strFieldName String field name
331 * @params strIoTSlaveObjectHostAdd String slave host address
332 * @params inStream ObjectInputStream communication
333 * @params inStream ObjectOutputStream communication
336 private void instrumentIoTSetDevice(String strFieldIdentifier, String strFieldName, String strIoTSlaveObjectHostAdd,
337 ObjectInputStream inStream, ObjectOutputStream outStream)
338 throws IOException, ClassNotFoundException, InterruptedException {
340 // Get information from the set
341 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
342 // Create a new IoTSet
343 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
344 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
345 int iRows = listObject.size();
346 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
347 // Transfer the address
348 for(int iRow=0; iRow<iRows; iRow++) {
349 arrFieldValues = listObject.get(iRow);
350 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
351 String strDeviceAddress = null;
352 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
353 strDeviceAddress = strIoTSlaveObjectHostAdd;
355 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
357 int iDestDeviceDriverPort = (int) arrFieldValues[1];
358 String strProtocol = (String) arrFieldValues[2];
359 // Check for wildcard feature
360 boolean bSrcPortWildCard = false;
361 boolean bDstPortWildCard = false;
362 if (arrFieldValues.length > 3) {
363 bSrcPortWildCard = (boolean) arrFieldValues[3];
364 bDstPortWildCard = (boolean) arrFieldValues[4];
366 // Add the port connection into communication handler - if it's not assigned yet
367 if (commHan.getComPort(strDeviceAddress) == null) {
368 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress);
370 // Send address one by one
371 Message msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
372 strDeviceAddress, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort,
373 bSrcPortWildCard, bDstPortWildCard);
374 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
376 // Reinitialize IoTSet on device object
377 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
378 "Reinitialize IoTSet fields!", inStream, outStream);
383 * A private method to instrument IoTSet Zigbee device
385 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
386 * @params strFieldName String field name
387 * @params strIoTSlaveObjectHostAdd String slave host address
388 * @params inStream ObjectInputStream communication
389 * @params inStream ObjectOutputStream communication
392 private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strFieldName, String strIoTSlaveObjectHostAdd,
393 ObjectInputStream inStream, ObjectOutputStream outStream)
394 throws IOException, ClassNotFoundException, InterruptedException {
396 // Get information from the set
397 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
398 // Create a new IoTSet
399 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
400 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
401 // Prepare ZigbeeConfig
402 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
403 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
404 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
405 commHan.addDevicePort(iZigbeeIoTMasterPort);
406 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort,
408 // Add the port connection into communication handler - if it's not assigned yet
409 if (commHan.getComPort(strZigbeeGWAddress) == null) {
410 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddress);
412 int iRows = setInstrumenter.numberOfRows();
413 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
414 // Transfer the address
415 for(int iRow=0; iRow<iRows; iRow++) {
416 arrFieldValues = setInstrumenter.fieldValues(iRow);
417 // Get device address
418 String strZBDevAddress = (String) arrFieldValues[0];
419 // Send policy to Zigbee gateway - TODO: Need to clear policy first?
420 zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddress), strZBDevAddress);
421 // Send address one by one
422 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT,
424 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
426 zbConfig.closeConnection();
427 // Reinitialize IoTSet on device object
428 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
429 "Reinitialize IoTSet fields!", inStream, outStream);
434 * A private method to instrument IoTSet of addresses
436 * @params strFieldIdentifier String field name + object ID
437 * @params strFieldName String field name
438 * @params inStream ObjectInputStream communication
439 * @params inStream ObjectOutputStream communication
442 private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
443 ObjectInputStream inStream, ObjectOutputStream outStream)
444 throws IOException, ClassNotFoundException, InterruptedException {
446 // Get information from the set
447 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
448 // Create a new IoTSet
449 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
450 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
451 int iRows = listObject.size();
452 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
453 // Transfer the address
454 for(int iRow=0; iRow<iRows; iRow++) {
455 arrFieldValues = listObject.get(iRow);
456 // Get device address
457 String strAddress = (String) arrFieldValues[0];
458 // Send address one by one
459 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT,
461 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
463 // Reinitialize IoTSet on device object
464 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
465 "Reinitialize IoTSet fields!", inStream, outStream);
470 * A private method to instrument an object on a specific machine and setting up policies
472 * @params strFieldObjectID String field object ID
475 private void instrumentObject(String strFieldObjectID) throws IOException {
477 // Extract the interface name for RMI
478 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
480 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
481 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
482 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
483 // Create an object name, e.g. ProximitySensorImplPS1
484 strObjName = strObjClassName + strFieldObjectID;
485 // Check first if host exists
486 if(commHan.objectExists(strObjName)) {
487 // If this object exists already ...
488 // Re-read IoTSlave object hostname for further reference
489 strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
490 RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
492 // If this is a new object ... then create one
493 // Get host address for IoTSlave from LoadBalancer
494 //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
495 strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
496 if (strIoTSlaveControllerHostAdd == null)
497 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
498 RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
499 // Add port connection and get port numbers
500 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
501 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
502 commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName,
503 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
504 // ROUTING POLICY: IoTMaster and device/controller object
505 // Master-slave communication
506 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
507 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
508 // ROUTING POLICY: Send the same routing policy to both the hosts
509 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
510 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
511 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
512 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
513 // Need to accommodate callback functions here - open ports for TCP
514 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
515 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
516 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
517 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
518 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
519 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
520 // Instrument the IoTSet declarations inside the class file
521 instrumentObjectIoTSet(strFieldObjectID);
523 // Send routing policy to router for controller object
524 // ROUTING POLICY: RMI communication - RMI registry and stub ports
525 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
526 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
527 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
528 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
529 // Send the same set of routing policies to compute nodes
530 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
531 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
532 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
533 STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
534 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
535 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
536 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
537 STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
538 // Send the same set of routing policies for callback ports
539 setCallbackPortsPolicy(strObjName, STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
543 * A private method to set router policies for callback ports
545 * @params strRouterAdd String router address
546 * @params strIoTSlaveControllerHostAdd String slave controller host address
547 * @params strIoTSlaveObjectHostAdd String slave object host address
548 * @params strProtocol String protocol
549 * @return iPort Integer port number
551 private void setCallbackPortsPolicy(String strObjName, String strRouterAdd, String strIoTSlaveControllerHostAdd,
552 String strIoTSlaveObjectHostAdd, String strProtocol) {
554 int iNumCallbackPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
555 Integer[] rmiCallbackPorts = commHan.getCallbackPorts(strObjName, iNumCallbackPorts);
556 // Iterate over port numbers and set up policies
557 for (int i=0; i<iNumCallbackPorts; i++) {
558 routerConfig.configureRouterMainPolicies(strRouterAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
559 strProtocol, rmiCallbackPorts[i]);
560 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
561 strProtocol, rmiCallbackPorts[i]);
562 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
563 strProtocol, rmiCallbackPorts[i]);
568 * A private method to set router policies for IoTDeviceAddress objects
570 * @params strFieldIdentifier String field name + object ID
571 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
572 * @params strIoTSlaveObjectHostAdd String slave host address
575 private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map,
576 String strIoTSlaveObjectHostAdd) {
578 // Get information from the set
579 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
580 int iRows = setInstrumenter.numberOfRows();
581 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
582 // Transfer the address
583 for(int iRow=0; iRow<iRows; iRow++) {
584 arrFieldValues = setInstrumenter.fieldValues(iRow);
585 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
586 // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
587 String strDeviceAddress = null;
588 if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
589 strDeviceAddress = strIoTSlaveObjectHostAdd;
591 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
593 int iDestDeviceDriverPort = (int) arrFieldValues[1];
594 String strProtocol = (String) arrFieldValues[2];
595 // Add the port connection into communication handler - if it's not assigned yet
596 if (commHan.getComPort(strDeviceAddress) == null) {
597 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddress);
599 // Send routing policy to router for device drivers and devices
600 // ROUTING POLICY: RMI communication - RMI registry and stub ports
601 if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
602 // Port number -1 means that we don't set the policy strictly to port number level
603 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
604 // ROUTING POLICY: Device driver and device
605 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
607 // ROUTING POLICY: Send to the compute node where the device driver is
608 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd,
609 strDeviceAddress, strProtocol);
610 } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
611 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
612 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
613 } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
614 // This is a TCP protocol that connects, e.g. a phone to our runtime system
615 // that provides a gateway access (accessed through destination port number)
616 commHan.addDevicePort(iDestDeviceDriverPort);
617 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
618 STR_TCP_PROTOCOL, iDestDeviceDriverPort);
619 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress,
620 STR_TCP_PROTOCOL, iDestDeviceDriverPort);
621 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
622 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
624 // Other port numbers...
625 commHan.addDevicePort(iDestDeviceDriverPort);
626 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress,
627 strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort);
628 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress,
629 strProtocol, commHan.getComPort(strDeviceAddress), iDestDeviceDriverPort);
635 * A private method to set router policies for IoTAddress objects
637 * @params strFieldIdentifier String field name + object ID
638 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
639 * @params strHostAddress String host address
642 private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map,
643 String strHostAddress) {
645 // Get information from the set
646 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
647 int iRows = setInstrumenter.numberOfRows();
648 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
649 // Transfer the address
650 for(int iRow=0; iRow<iRows; iRow++) {
651 arrFieldValues = setInstrumenter.fieldValues(iRow);
652 objAddInitHand.addField(strFieldIdentifier, arrFieldValues); // Save this for object instantiation
653 // Get device address
654 String strAddress = (String) arrFieldValues[0];
655 // Setting up router policies for HTTP/HTTPs
656 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
657 routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
662 * A private method to instrument an object's IoTSet and IoTRelation field to up policies
664 * Mostly the IoTSet fields would contain IoTDeviceAddress objects
666 * @params strFieldObjectID String field object ID
669 private void instrumentObjectIoTSet(String strFieldObjectID) throws IOException {
671 // If this is a new object ... then create one
672 // Instrument the class source code and look for IoTSet for device addresses
673 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
674 String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
675 FileInputStream fis = new FileInputStream(strObjectClassNamePath);
676 ClassReader cr = new ClassReader(fis);
677 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
678 // We need Object ID to instrument IoTDeviceAddress
679 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
682 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " +
683 strFieldObjectID, BOOL_VERBOSE);
684 // Get the object and the class names
685 // Build objects for IoTSet and IoTRelation fields in the device object classes
686 mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
687 HashMap<String,Object> hmObjectFieldObjects = crim.getFieldObjects();
688 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
689 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
690 // Iterate over HashMap and choose between processing
691 String strFieldName = map.getKey();
692 String strClassName = map.getValue().getClass().getName();
693 String strFieldIdentifier = strFieldName + strFieldObjectID;
694 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
695 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
696 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
697 // Instrument the normal IoTDeviceAddress
698 setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
699 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
700 // Instrument the IoTAddress
701 setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
702 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
703 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
704 RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..",
707 String strErrMsg = "IoTMaster: Device driver object" +
708 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
709 " or IoTSet<IoTZigbeeAddress>!";
710 throw new Error(strErrMsg);
713 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
714 throw new Error(strErrMsg);
721 * A private method to create an object on a specific machine
723 * @params strObjName String object name
724 * @params strObjClassName String object class name
725 * @params strObjClassInterfaceName String object class interface name
726 * @params strIoTSlaveObjectHostAdd String IoTSlave host address
727 * @params strFieldObjectID String field object ID
728 * @params arrFieldValues Array of field values
729 * @params arrFieldClasses Array of field classes
732 private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
733 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses)
734 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
741 start = System.currentTimeMillis();
743 // Construct ssh command line
744 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
745 // java -cp $CLASSPATH:./*.jar
746 // -Djava.rmi.server.codebase=file:./*.jar
747 // iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
748 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
749 String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
750 STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
751 strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
752 commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
753 commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
754 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
755 // Start a new thread to start a new JVM
756 createThread(strSSHCommand);
757 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
758 Socket socket = serverSocket.accept();
759 ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
760 ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
763 result = System.currentTimeMillis()-start;
764 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
767 start = System.currentTimeMillis();
769 // Create message to transfer file first
770 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
771 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
772 File file = new File(sPath);
773 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
774 "Sending file!", inStream, outStream);
775 // Send file - JAR file for object creation
776 sendFile(serverSocket.accept(), sPath, file.length());
777 Message msgReply = (Message) inStream.readObject();
778 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
781 result = System.currentTimeMillis()-start;
782 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
785 start = System.currentTimeMillis();
787 // Pack object information to create object on a IoTSlave
788 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
789 strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
790 commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
792 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
793 // Instrument the class source code and look for IoTSet for device addresses
794 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
795 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " +
796 strFieldObjectID, BOOL_VERBOSE);
797 // Get the object and the class names
798 // Build objects for IoTSet and IoTRelation fields in the device object classes
799 ClassRuntimeInstrumenterMaster crim = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
800 HashMap<String,Object> hmObjectFieldObjects = crim.getFieldObjects();
801 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
802 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
803 // Iterate over HashMap and choose between processing
804 String strFieldName = map.getKey();
805 String strClassName = map.getValue().getClass().getName();
806 String strFieldIdentifier = strFieldName + strFieldObjectID;
807 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
808 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
809 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
810 // Instrument the normal IoTDeviceAddress
812 instrumentIoTSetDevice(strFieldIdentifier, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
814 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
815 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
817 instrumentIoTSetZBDevice(map, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
819 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
820 // Instrument the IoTAddress
822 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream);
825 String strErrMsg = "IoTMaster: Device driver object" +
826 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
827 " or IoTSet<IoTZigbeeAddress>!";
828 throw new Error(strErrMsg);
831 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
832 throw new Error(strErrMsg);
836 // TODO: Change this later
837 outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
840 result = System.currentTimeMillis()-start;
841 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
847 serverSocket.close();
852 * A private method to create controller objects
856 private void createControllerObjects() throws InterruptedException {
858 // Create a list of threads
859 List<Thread> threads = new ArrayList<Thread>();
860 // Get the list of active controller objects and loop it
861 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
862 for(String strObjName : listActiveControllerObject) {
864 ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
865 Thread objectThread = new Thread(new Runnable() {
869 createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
870 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(),
871 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName),
872 commHan.getArrayFieldClasses(strObjName));
873 } catch (IOException |
874 ClassNotFoundException |
875 InterruptedException ex) {
876 ex.printStackTrace();
881 threads.add(objectThread);
882 objectThread.start();
885 for (Thread thread : threads) {
888 } catch (InterruptedException ex) {
889 ex.printStackTrace();
896 * A private method to instrument IoTSet
898 * @params Map.Entry<String,Object> Entry of map IoTSet instrumentation
899 * @params strFieldName String field name
902 private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName)
903 throws IOException, ClassNotFoundException, InterruptedException {
905 // Get information from the set
906 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
907 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
909 int iRows = setInstrumenter.numberOfRows();
910 for(int iRow=0; iRow<iRows; iRow++) {
911 // Get field classes and values
912 arrFieldClasses = setInstrumenter.fieldClasses(iRow);
913 arrFieldValues = setInstrumenter.fieldValues(iRow);
914 // Get object ID and class name
915 String strObjID = setInstrumenter.fieldObjectID(iRow);
916 strObjClassName = setInstrumenter.fieldEntryType(strObjID);
917 // Call the method to create an object
918 instrumentObject(strObjID);
919 int iNumOfPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
920 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
921 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName),
922 commHan.getRMIStubPort(strObjName), commHan.getCallbackPorts(strObjName, iNumOfPorts));
928 * A private method to instrument IoTRelation
930 * @params Map.Entry<String,Object> Entry of map IoTRelation instrumentation
931 * @params strFieldName String field name
934 private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName)
935 throws IOException, ClassNotFoundException, InterruptedException {
937 // Get information from the set
938 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
939 int iRows = relationInstrumenter.numberOfRows();
940 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
942 for(int iRow=0; iRow<iRows; iRow++) {
943 // Operate on the first set first
944 arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
945 arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
946 String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
947 strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
948 // Call the method to create an object
949 instrumentObject(strObjID);
950 // Get the first object controller host address
951 String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
952 int iNumOfPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
953 objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
954 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
955 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName),
956 commHan.getCallbackPorts(strObjName, iNumOfPorts));
957 // Operate on the second set
958 arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
959 arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
960 strObjID = relationInstrumenter.secondFieldObjectID(iRow);
961 strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
962 // Call the method to create an object
963 instrumentObject(strObjID);
964 // Get the second object controller host address
965 String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
966 objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
967 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
968 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName),
969 commHan.getCallbackPorts(strObjName, iNumOfPorts));
971 // ROUTING POLICY: first and second controller objects in IoTRelation
972 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
973 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
974 // ROUTING POLICY: Send the same routing policy to both the hosts
975 routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
976 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
977 routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
978 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
983 * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
985 * @params inStream ObjectInputStream communication
986 * @params outStream ObjectOutputStream communication
989 private void initializeSetsAndRelations(ObjectInputStream inStream, ObjectOutputStream outStream)
990 throws IOException, ClassNotFoundException {
991 // Get list of fields
992 List<String> strFields = objInitHand.getListOfFields();
993 // Iterate on HostAddress
994 for(String str : strFields) {
995 IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
996 if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
997 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
998 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
999 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1000 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1001 for (ObjectInitInfo objInitInfo : listObject) {
1002 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1003 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1004 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(),
1005 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(),
1006 objInitInfo.getRMICallbackPorts()), "Get IoTSet object!", inStream, outStream);
1008 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1009 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1010 "Renitialize IoTSet field!", inStream, outStream);
1011 } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1012 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1013 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1014 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1015 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1016 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1017 Iterator it = listSecondObject.iterator();
1018 for (ObjectInitInfo objInitInfo : listObject) {
1019 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1020 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT,
1021 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1022 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1023 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), objInitInfo.getRMICallbackPorts()),
1024 "Get IoTRelation first object!", inStream, outStream);
1025 ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1026 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1027 commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1028 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1029 objSecObj.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1030 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), objSecObj.getRMICallbackPorts()),
1031 "Get IoTRelation second object!", inStream, outStream);
1033 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1034 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1035 "Renitialize IoTRelation field!", inStream, outStream);
1041 * A method to set router basic policies at once
1043 * @param strRouter String router name
1046 private void setRouterBasicPolicies(String strRouter) {
1048 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1049 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1050 routerConfig.configureRouterDHCPPolicies(strRouter);
1051 routerConfig.configureRouterDNSPolicies(strRouter);
1052 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1053 routerConfig.configureRejectPolicies(strRouter);
1057 * A method to set host basic policies at once
1059 * @param strHost String host name
1062 private void setHostBasicPolicies(String strHost) {
1064 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1065 routerConfig.configureHostDHCPPolicies(strHost);
1066 routerConfig.configureHostDNSPolicies(strHost);
1067 if (strHost.equals(strMonitorHost)) {
1068 // Check if this is the monitoring host
1069 routerConfig.configureHostICMPPolicies(strHost);
1070 routerConfig.configureHostSSHPolicies(strHost);
1072 routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1073 routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1075 // Apply SQL allowance policies to master host
1076 if (strHost.equals(strIoTMasterHostAdd)) {
1077 routerConfig.configureHostSQLPolicies(strHost);
1079 routerConfig.configureRejectPolicies(strHost);
1083 * A method to create a thread for policy deployment
1085 * @param strRouterAddress String router address to configure
1086 * @param setHostAddresses Set of strings for host addresses to configure
1089 private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1091 // Create a list of threads
1092 List<Thread> threads = new ArrayList<Thread>();
1093 // Start threads for hosts
1094 for(String strAddress : setHostAddresses) {
1095 Thread policyThread = new Thread(new Runnable() {
1097 synchronized(this) {
1098 routerConfig.sendHostPolicies(strAddress);
1102 threads.add(policyThread);
1103 policyThread.start();
1104 RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1106 // A thread for router
1107 Thread policyThread = new Thread(new Runnable() {
1109 synchronized(this) {
1110 routerConfig.sendRouterPolicies(strRouterAddress);
1114 threads.add(policyThread);
1115 policyThread.start();
1116 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);
1118 for (Thread thread : threads) {
1121 } catch (InterruptedException ex) {
1122 ex.printStackTrace();
1129 * A method to assign objects to multiple JVMs, including
1130 * the controller/device object that uses other objects
1131 * in IoTSet and IoTRelation
1135 private void createObjects() {
1142 // Extract hostname for this IoTMaster from MySQL DB
1143 strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1144 // Loop as we can still find controller/device classes
1145 for(int i=0; i<strObjectNames.length; i++) {
1147 start = System.currentTimeMillis();
1149 // Assign a new list of PrintWriter objects
1150 routerConfig.renewPrintWriter();
1151 // Get controller names one by one
1152 String strObjControllerName = strObjectNames[i];
1153 // Use LoadBalancer to assign a host address
1154 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1155 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1156 if (strIoTSlaveControllerHostAdd == null)
1157 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1158 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1159 // Add port connection and get port numbers
1160 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1161 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1162 // ROUTING POLICY: IoTMaster and main controller object
1163 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1164 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1165 // ROUTING POLICY: Send the same routing policy to both the hosts
1166 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1167 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1168 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1169 strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1171 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1172 String strSSHCommand = STR_SSH_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1173 STR_RUNTIME_DIR + " sudo java " + STR_CLS_PATH + " " +
1174 STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1175 commHan.getComPort(strObjControllerName) + " " +
1176 commHan.getRMIRegPort(strObjControllerName) + " " +
1177 commHan.getRMIStubPort(strObjControllerName) + " >& " +
1178 STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1179 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1180 createThread(strSSHCommand);
1181 // Wait for connection
1182 // Create a new socket for communication
1183 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1184 Socket socket = serverSocket.accept();
1185 ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
1186 ObjectOutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
1187 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1190 result = System.currentTimeMillis()-start;
1191 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
1193 start = System.currentTimeMillis();
1195 // Send files for every controller class
1196 // e.g. AcmeProximity.jar and AcmeProximity.zip
1197 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
1198 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1199 strControllerClassName;
1201 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1202 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1203 strControllerJarName;
1204 File file = new File(strControllerJarNamePath);
1205 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1206 "Sending file!", inStream, outStream);
1207 // Send file - Class file for object creation
1208 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1209 Message msgReply = (Message) inStream.readObject();
1210 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1211 // Send .zip file if additional zip file is specified
1212 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1213 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1214 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1215 if (strAdditionalFile.equals(STR_YES)) {
1216 String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1217 String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1218 strControllerCmpName;
1219 file = new File(strControllerCmpNamePath);
1220 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1221 "Sending file!", inStream, outStream);
1222 // Send file - Class file for object creation
1223 sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1224 msgReply = (Message) inStream.readObject();
1225 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1227 // Create main controller/device object
1228 commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
1229 "Create main object!", inStream, outStream);
1232 result = System.currentTimeMillis()-start;
1233 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
1234 System.out.println(" ==> Including file transfer times!\n\n");
1236 start = System.currentTimeMillis();
1238 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1239 // Instrumenting one file
1240 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
1241 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
1242 FileInputStream fis = new FileInputStream(strControllerClassNamePath);
1243 ClassReader cr = new ClassReader(fis);
1244 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
1245 ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
1248 // Get the object and the class names
1249 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
1250 HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
1251 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
1252 RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1253 // Iterate over HashMap and choose between processing
1254 // SetInstrumenter vs. RelationInstrumenter
1255 String strFieldName = map.getKey();
1256 String strClassName = map.getValue().getClass().getName();
1257 if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1258 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1259 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) {
1260 String strErrMsg = "IoTMaster: Controller object" +
1261 " cannot have IoTSet<IoTDeviceAddress>!";
1262 throw new Error(strErrMsg);
1263 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) {
1264 String strErrMsg = "IoTMaster: Controller object" +
1265 " cannot have IoTSet<ZigbeeAddress>!";
1266 throw new Error(strErrMsg);
1267 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) {
1268 // Instrument the IoTAddress
1269 setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
1270 instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream);
1273 instrumentIoTSet(map, strFieldName);
1275 } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
1276 instrumentIoTRelation(map, strFieldName);
1280 result = System.currentTimeMillis()-start;
1281 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
1282 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
1285 start = System.currentTimeMillis();
1287 // ROUTING POLICY: Deploy basic policies if this is the last controller
1288 if (i == strObjectNames.length-1) {
1289 // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
1290 for(String s: commHan.getHosts()) {
1291 setHostBasicPolicies(s);
1293 // We retain all the basic policies for router,
1294 // but we delete the initial allowance policies for internal all TCP and UDP communications
1295 setRouterBasicPolicies(STR_ROUTER_ADD);
1297 // Close access to policy files and deploy policies
1298 routerConfig.close();
1299 // Deploy the policy
1300 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
1301 setAddresses.add(strIoTMasterHostAdd);
1302 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
1305 result = System.currentTimeMillis()-start;
1306 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
1309 start = System.currentTimeMillis();
1311 // Separating object creations and Set/Relation initializations
1312 createControllerObjects();
1315 result = System.currentTimeMillis()-start;
1316 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
1318 start = System.currentTimeMillis();
1320 // Sets and relations initializations
1321 initializeSetsAndRelations(inStream, outStream);
1324 result = System.currentTimeMillis()-start;
1325 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
1327 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
1328 commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD),
1329 "Invoke init() method!", inStream, outStream);
1330 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
1331 outStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1335 serverSocket.close();
1336 commHan.printLists();
1337 lbIoT.printHostInfo();
1340 } catch (IOException |
1341 InterruptedException |
1342 ClassNotFoundException ex) {
1343 System.out.println("IoTMaster: Exception: "
1345 ex.printStackTrace();
1349 public static void main(String args[]) {
1351 // Detect the available controller/device classes
1352 // Input args[] should be used to list the controllers/devices
1353 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
1354 IoTMaster iotMaster = new IoTMaster(args);
1356 iotMaster.parseIoTMasterConfigFile();
1357 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
1358 iotMaster.initLiveDataStructure();
1360 iotMaster.createObjects();