4 #include "IoTSlave.hpp"
6 IoTSlave::IoTSlave(string _serverAddress, int _serverPort, string _objectName) {
8 //isDriverObject = false; // Default to false
9 serverAddress = _serverAddress;
10 serverPort = _serverPort;
11 objectName = _objectName;
12 socket = new TCPSocket(serverAddress, serverPort);
14 writeToFile("IoTSlave object created! Connection established!");
18 IoTSlave::~IoTSlave() {
24 /*if (objMainCls != NULL) {
28 if (objSkelCls != NULL) {
32 for (IoTSet<void*>* iotset : vecIoTSet) {
40 // Private helper functions
41 int* IoTSlave::byteToInt(int* result, char* bytes) {
44 memcpy(&i, bytes, sizeof(int));
51 char* IoTSlave::intToByteArray(int i, char* bytes) {
53 int iInvert = htobe32(i);
54 memcpy(bytes, &iInvert, sizeof(int));
60 void* IoTSlave::getObjectConverted(void* retObj, string object, string objectClass) {
62 // Returning new objects in heap - so we need to delete them afterwards
63 if (objectClass.compare(STRINGCLASS) == 0) {
64 string* retStr = new string(object);
66 } else if (objectClass.compare(INTCLASS) == 0) {
67 int* retInt = new int(atoi(object.c_str()));
69 } else // return NULL if class is not identifiable
76 // Factoring out iteration
77 char* IoTSlave::recvIter(char* recvBuffer, int recvLen) {
79 int bytesReceived = 0; // Bytes read on each recv()
80 int totalBytesReceived = 0; // Total bytes read
82 while (totalBytesReceived < recvLen) {
83 // Receive up to the buffer size bytes from the sender
84 if ((bytesReceived = (socket->recv(recvBuffer, RCVBUFSIZE))) <= 0) {
85 string errMsg = "IoTSlave: Unable to read!";
86 cerr << errMsg << endl;
90 totalBytesReceived += bytesReceived; // Keep tally of total bytes
97 // Factoring out iteration
98 char* IoTSlave::recvFileIter(char* recvBuffer, int recvLen) {
100 int bytesReceived = 0; // Bytes read on each recv()
101 int totalBytesReceived = 0; // Total bytes read
103 while (totalBytesReceived < recvLen) {
104 // Receive up to the buffer size bytes from the sender
105 if ((bytesReceived = (socket->recv(recvBuffer, recvLen))) <= 0) {
106 string errMsg = "IoTSlave: Unable to read!";
107 cerr << errMsg << endl;
111 totalBytesReceived += bytesReceived; // Keep tally of total bytes
118 void IoTSlave::openFile(string fileName) {
120 log.open(FILEPATH + fileName + FILEEXT);
124 void IoTSlave::writeToFile(string logMsg) {
126 log << "IoTSlave: " << logMsg << endl;
130 void IoTSlave::closeFile() {
136 void IoTSlave::getObjectHandler(string objectClassName) {
139 string strObj = FILEPATH + objectClassName + SOEXT;
140 void* handle = dlopen (strObj.c_str(), RTLD_LAZY);
142 fputs (dlerror(), stderr);
143 writeToFile("Error handling object!");
146 writeToFile("Object handled!");
148 string createFunction = CREATEFUNCTION + objectClassName;
149 create_object = (create_t*) dlsym(handle, createFunction.c_str());
150 const char* dlsym_error = dlerror();
152 cerr << "Cannot load symbol create: " << dlsym_error << '\n';
153 writeToFile("Cannot load symbol create!");
156 writeToFile("Object factory created for " + objectClassName);
158 string destroyFunction = DESTROYFUNCTION + objectClassName;
159 destroy_object = (destroy_t*) dlsym(handle, destroyFunction.c_str());
160 dlsym_error = dlerror();
162 cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
163 writeToFile("Cannot load symbol destroy!");
166 writeToFile("Object destroyer created for " + objectClassName);
167 // Create initializer
168 string initFunction = INITFUNCTION + objectClassName;
169 init_object = (init_t*) dlsym(handle, initFunction.c_str());
170 dlsym_error = dlerror();
172 cerr << "Cannot load symbol init: " << dlsym_error << '\n';
173 writeToFile("Cannot load symbol init!");
176 writeToFile("Object initializer created for " + objectClassName);
180 // Run init_object function
181 void IoTSlave::runInitObject(IoTSlave* iotslave) {
183 iotslave->init_object(iotslave->objMainCls);
187 // Instantiate main object!
188 // Use handler obtained by getObjectHandler() and instantiate object!
189 void IoTSlave::instantiateMainObject() {
191 // IoTSet + IoTRelation objects
192 int paramSize = vecIoTSet.size() + vecIoTRel.size();
193 void* params[paramSize];
195 for(int i=0; i<vecIoTSet.size(); i++) {
196 params[j] = vecIoTSet[i]; j++;
198 writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
199 for(int i=0; i<vecIoTRel.size(); i++) {
200 params[j] = vecIoTRel[i]; j++;
202 writeToFile("Vector IoTRelation size: " + to_string(vecIoTRel.size()));
203 objMainCls = create_object(params);
204 writeToFile("Object created for " + mainObjectName);
205 init_object(objMainCls);
206 //thread th1 (&IoTSlave::runInitObject, this, this);
208 //thread th1 (&IoTSlave::runInitObject, this, this);
210 writeToFile("Initialized object " + mainObjectName);
214 // Instantiate driver object!
215 // Use handler obtained by getObjectHandler() and instantiate object!
216 void IoTSlave::instantiateDriverObject() {
218 // IoTDeviceAddress + other arguments
219 int paramSize = vecIoTSet.size() + args.size();
220 void* params[paramSize];
221 for(int i=0; i<vecIoTSet.size(); i++) {
222 params[i] = vecIoTSet[i]; // Just the first object is taken in this case
224 writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
225 writeToFile("Arg size: " + to_string(args.size()));
226 int countArg = vecIoTSet.size(); // Start from after the address set
227 // Iterate over arguments
228 for(int i=0; i<args.size(); i++) {
229 params[countArg] = getObjectConverted(params[countArg], args[i], argClasses[i]);
232 objMainCls = create_object(params);
233 // Delete unused object after conversion and instantiation
234 for(int i=1; i<paramSize; i++) {
235 if (argClasses[i-1].compare(STRINGCLASS) == 0) {
236 delete (string*) params[i];
237 } else if (argClasses[i-1].compare(INTCLASS) == 0)
238 delete (int*) params[i];
240 writeToFile("Object created for " + objectClassName);
244 // Use handler obtained by getObjectHandler() and instantiate skeleton object!
245 void IoTSlave::instantiateSkelObject() {
247 void* params[SKELPARAMSIZE];
248 params[0] = objMainCls;
249 //string callbackAddress = LOCALHOST;
250 //params[1] = &callbackAddress;
251 //params[2] = &objectStubPort;
252 params[1] = &objectStubPort;
253 params[2] = &objectRegPort;
254 writeToFile("Skeleton Object " + objectSkelClass + " created for " + objectClassName);
255 // After this, this slave needs to be killed using "pkill IoTSlave" because it's waiting in an infinite while-loop
256 objSkelCls = create_object(params);
260 // Use handler obtained by getObjectHandler() and instantiate stub object!
261 void IoTSlave::instantiateStubObject() {
263 void* params[STUBPARAMSIZE];
264 params[0] = &objectStubPort;
265 params[1] = &objectRegPort;
266 params[2] = &hostAddress;
267 //params[0] = &objectStubPort;
268 //params[1] = &hostAddress;
269 //string callbackAddress = LOCALHOST;
270 //params[2] = &callbackAddress;
276 writeToFile("Stub Object " + objectStubClass + " created for " + objectClassName);
277 writeToFile("Success 1!");
278 objStubCls = create_object(params);
279 writeToFile("Success 2!");
284 string IoTSlave::getServerAddress() {
286 return serverAddress;
290 int IoTSlave::getServerPort() {
296 string IoTSlave::getObjectName() {
302 void IoTSlave::sendInteger(int intSend) {
304 char charInt[sizeof(int)];
305 // Convert int to byte array and fix endianness
306 intToByteArray(intSend, charInt);
307 // Send the length first
308 void* toSend = charInt;
309 socket->send(toSend, sizeof(int));
313 int IoTSlave::recvInteger() {
315 int toBeReceived = sizeof(int);
316 char recvInt[sizeof(int)]; // Normally 4 bytes
318 // Receive and iterate until complete
319 //writeToFile("Receiving Integer! Size: " + to_string(toBeReceived));
320 recvIter(recvInt, toBeReceived);
323 byteToInt(&retVal, recvInt);
329 void IoTSlave::sendString(string strSend) {
331 // Send the length first
332 int strLen = strSend.length();
336 char* chStrSend = new char[strLen];
337 strcpy(chStrSend, strSend.c_str());
338 void* toSend = chStrSend;
339 socket->send(toSend, strLen);
345 string IoTSlave::recvString() {
347 // Get the length of string first
348 int strLen = recvInteger();
349 char* recvStr = new char[strLen];
351 // Receive and iterate until complete
352 //writeToFile("Receiving String! Size: " + to_string(strLen));
353 recvIter(recvStr, strLen);
355 string retVal(recvStr, strLen);
362 // Receive file from IoTMaster
363 void IoTSlave::transferFile() {
365 string fileName = recvFile(); sendAck();
366 //unzipFile(fileName);
370 void IoTSlave::unzipFile(string fileName) {
372 // Unzip file (what we are sending is a zipped file)
373 // TODO: perhaps we need to replace this with libzip or zlib later
374 writeToFile("Unzipping file!");
375 string chmodCmd = FILEPATH + fileName + SHELL;
376 //std::system(chmodCmd.c_str());
377 thread th1 (std::system, chmodCmd.c_str());
379 writeToFile("Finished unzipping file!");
383 string IoTSlave::recvFile() {
385 // Get the length of string first
386 string fileName = recvString(); sendAck();
387 int fileLen = recvInteger(); sendAck();
388 writeToFile("Receiving file " + fileName + " with length " + to_string(fileLen) + " bytes...");
389 char* recvFil = new char[fileLen];
390 // Receive and iterate until complete
391 recvFileIter(recvFil, fileLen);
394 fileStream.open(FILEPATH + fileName);
396 writeToFile("Error opening file: " + FILEPATH + fileName);
399 fileStream.write(recvFil, fileLen);
402 // TODO: Experimental
403 //string chmodCmd = FILEPATH + fileName + SHELL;
404 //execv(chmodCmd.c_str(), 0);
409 // Create a driver object, e.g. LifxLightBulb
410 void IoTSlave::createObject() {
412 writeToFile("Creating a driver object now...");
413 // Receiving object info
414 objectName = recvString(); sendAck();
415 writeToFile("=> Driver object name: " + objectName);
416 objectClassName = recvString(); sendAck();
417 writeToFile("=> Driver object class name: " + objectClassName);
418 objectInterfaceName = recvString(); sendAck();
419 writeToFile("=> Driver object interface name: " + objectInterfaceName);
420 objectSkelClass = recvString(); sendAck();
421 writeToFile("=> Driver object skeleton class name: " + objectSkelClass);
422 objectRegPort = recvInteger(); sendAck();
423 writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
424 objectStubPort = recvInteger(); sendAck();
425 writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
426 int numOfArgs = recvInteger(); sendAck();
427 writeToFile("=> Number of args: " + to_string(numOfArgs));
428 for (int i = 0; i < numOfArgs; i++) {
429 string arg = recvString(); sendAck();
431 writeToFile("==> Got argument: " + arg);
433 for (int i = 0; i < numOfArgs; i++) {
434 string argClass = recvString(); sendAck();
435 argClasses.push_back(argClass);
436 writeToFile("==> Got argument class: " + argClass);
438 // We are just receiving object information here
439 // Instantiation will be done when IoTDeviceAddress has been sent
443 // Create a new IoTSet object to hold objects
444 void IoTSlave::createNewIoTSet() {
446 objectFieldName = recvString(); sendAck();
447 // Instantiating new IoTSet object
448 isetObject = new unordered_set<void*>();
449 writeToFile("Creating new IoTSet for field: " + objectFieldName);
453 // Get IoTDeviceAddress object reference and put it inside IoTSet object
454 void IoTSlave::getDeviceIoTSetObject() {
456 writeToFile("Getting IoTDeviceAddress... ");
457 // Get the IoTDeviceAddress info
458 hostAddress = recvString(); sendAck();
459 writeToFile("=> Host address: " + hostAddress);
460 int sourcePort = recvInteger(); sendAck();
461 writeToFile("=> Source port: " + to_string(sourcePort));
462 int destPort = recvInteger(); sendAck();
463 writeToFile("=> Destination port: " + to_string(destPort));
464 bool sourcePortWildCard = (bool) recvInteger(); sendAck();
465 writeToFile("=> Is source port wild card? " + to_string(sourcePortWildCard));
466 bool destPortWildCard = (bool) recvInteger(); sendAck();
467 writeToFile("=> Is destination port wild card? " + to_string(destPortWildCard));
468 // Create IoTDeviceAddress
469 IoTDeviceAddress* objDeviceAddress = new IoTDeviceAddress(hostAddress, sourcePort, destPort,
470 sourcePortWildCard, destPortWildCard);
471 // Insert it into isetObject!
472 isetObject->insert(objDeviceAddress);
473 writeToFile("=> Inserting IoTDeviceAddress into set...");
474 writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
476 //isDriverObject = true;
480 void IoTSlave::createStub() {
481 // Create Stub object
482 unordered_map<string,void*>::const_iterator itr = mapObjNameStub.find(objectName);
483 if (itr != mapObjNameStub.end()) { // Stub has been created earlier
484 writeToFile("=> Stub has been created! Getting back reference...");
485 objStubCls = itr->second;
486 } else { // Instantiate a new stub and map it
487 writeToFile("=> Stub has not been created! Creating a new stub...");
488 getObjectHandler(objectStubClass);
489 instantiateStubObject();
490 mapObjNameStub.insert(make_pair(objectName,objStubCls));
491 writeToFile("=> Map has: " + to_string(mapObjNameStub.size()) + " members");
492 // vector<int> for ports has been copied - now delete it
498 // Get IoTSet object content reference and put it inside IoTSet object
499 // This is basically the stub objects
500 void IoTSlave::getIoTSetObject() {
502 writeToFile("Getting IoTSet object... ");
503 getIoTSetRelationObject();
505 // Insert it into isetObject!
506 isetObject->insert(objStubCls);
507 writeToFile("=> Inserting stub object into set...");
508 writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
512 // Reinitialize IoTSet field!
513 void IoTSlave::reinitializeIoTSetField() {
515 writeToFile("Reinitialize IoTSet field...");
516 iotsetObject = new IoTSet<void*>(isetObject);
517 // Collect IoTSet field first in a vector
518 vecIoTSet.push_back(iotsetObject);
523 // Instantiate driver object
524 void IoTSlave::createDriverObject() {
526 // Instantiate driver object
527 getObjectHandler(objectClassName);
528 instantiateDriverObject();
529 // Instantiate skeleton object
530 getObjectHandler(objectSkelClass);
531 instantiateSkelObject();
535 // Create a new IoTRelation object to hold objects
536 void IoTSlave::createNewIoTRelation() {
538 objectFieldName = recvString(); sendAck();
539 // Instantiating new IoTSet object
540 irelObject = new unordered_multimap<void*,void*>();
541 writeToFile("Creating new IoTRelation for field: " + objectFieldName);
545 // Get IoTRelation object
546 void IoTSlave::getIoTSetRelationObject() {
548 hostAddress = recvString(); sendAck();
549 writeToFile("=> Host address: " + hostAddress);
550 objectName = recvString(); sendAck();
551 writeToFile("=> Driver object name: " + objectName);
552 objectClassName = recvString(); sendAck();
553 writeToFile("=> Driver object class name: " + objectClassName);
554 objectInterfaceName = recvString(); sendAck();
555 writeToFile("=> Driver object interface name: " + objectInterfaceName);
556 objectStubClass = recvString(); sendAck();
557 writeToFile("=> Driver object stub class name: " + objectStubClass);
558 objectRegPort = recvInteger(); sendAck();
559 writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
560 objectStubPort = recvInteger(); sendAck();
561 writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
562 int numOfPorts = recvInteger(); sendAck();
563 ports = new vector<int>();
564 for (int i = 0; i < numOfPorts; i++) {
565 int port = recvInteger(); sendAck();
566 ports->push_back(port);
567 writeToFile("==> Got a new port: " + to_string(port));
572 // Get the first object of IoTRelation
573 void IoTSlave::getIoTRelationFirstObject() {
575 writeToFile("Getting IoTRelation first object... ");
576 getIoTSetRelationObject();
578 // Hold the first object of IoTRelation
579 irelFirstObject = objStubCls;
580 writeToFile("=> Holding first stub object...");
584 // Get the second object of IoTRelation
585 void IoTSlave::getIoTRelationSecondObject() {
587 writeToFile("Getting IoTRelation second object... ");
588 getIoTSetRelationObject();
590 // Hold the first object of IoTRelation
591 irelSecondObject = objStubCls;
592 writeToFile("=> Holding second stub object...");
593 pair<void*,void*>* iotrelPair = new pair<void*,void*>(irelFirstObject, irelSecondObject);
594 writeToFile("=> Creating a pair of stub objects and inserting into IoTRelation object...");
595 irelObject->insert(*iotrelPair);
599 // Reinitialize IoTRelation
600 void IoTSlave::reinitializeIoTRelationField() {
602 writeToFile("Reinitialize IoTRelation field...");
603 iotrelObject = new IoTRelation<void*,void*>(irelObject);
604 // Collect IoTSet field first in a vector
605 vecIoTRel.push_back(iotrelObject);
609 // Invoke init() method in main controller
610 void IoTSlave::invokeInitMethod() {
612 writeToFile("Invoke init() method for: " + mainObjectName);
613 // Instantiate main controller object
614 getObjectHandler(mainObjectName);
615 instantiateMainObject();
620 // Create a main object, e.g. Lifxtest
621 void IoTSlave::createMainObject() {
623 mainObjectName = recvString(); sendAck();
624 writeToFile("Creating main object: " + mainObjectName);
625 // Just receive the name of the class object here
626 // We will instantiate the object after we get the set/relation objects
630 void IoTSlave::sendAck() {
632 int codeAck = (int) ACKNOWLEDGED;
633 sendInteger(codeAck);
637 bool IoTSlave::recvEndTransfer() {
639 int codeEndTransfer = (int) END_TRANSFER;
640 int recvCode = recvInteger();
641 if (recvCode == codeEndTransfer)
647 void IoTSlave::commIoTMaster() {
649 writeToFile("Starting main loop...");
650 // Main iteration/loop
652 IoTCommCode message = (IoTCommCode) recvInteger();
653 writeToFile("Message: " + to_string(message));
666 case CREATE_MAIN_OBJECT:
670 case CREATE_NEW_IOTSET:
674 case CREATE_NEW_IOTRELATION:
675 createNewIoTRelation();
678 case GET_IOTSET_OBJECT:
682 case GET_IOTRELATION_FIRST_OBJECT:
683 getIoTRelationFirstObject();
686 case GET_IOTRELATION_SECOND_OBJECT:
687 getIoTRelationSecondObject();
690 case REINITIALIZE_IOTSET_FIELD:
691 reinitializeIoTSetField();
694 case REINITIALIZE_IOTRELATION_FIELD:
695 reinitializeIoTRelationField();
698 case GET_DEVICE_IOTSET_OBJECT:
699 getDeviceIoTSetObject();
702 case GET_ZB_DEV_IOTSET_OBJECT:
703 //getZBDevIoTSetObject();
706 case GET_ADD_IOTSET_OBJECT:
707 //getAddIoTSetObject();
710 case INVOKE_INIT_METHOD:
714 case CREATE_DRIVER_OBJECT:
715 createDriverObject();
728 writeToFile("End of loop!");
732 int main(int argc, char *argv[]) {
734 string serverAddress = argv[1];
735 char* servPort = argv[2];
736 int serverPort = atoi(servPort);
737 string strObjName = argv[3];
738 IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort, strObjName);
740 iotSlave->commIoTMaster();