4 #include "IoTSlave.hpp"
6 #include "Lifxtest.cpp"
8 IoTSlave::IoTSlave(string _serverAddress, int _serverPort, string _objectName) {
10 //isDriverObject = false; // Default to false
11 serverAddress = _serverAddress;
12 serverPort = _serverPort;
13 objectName = _objectName;
14 socket = new TCPSocket(serverAddress, serverPort);
16 writeToFile("IoTSlave object created! Connection established!");
20 IoTSlave::~IoTSlave() {
26 /*if (objMainCls != NULL) {
30 if (objSkelCls != NULL) {
34 for (IoTSet<void*>* iotset : vecIoTSet) {
42 // Private helper functions
43 int* IoTSlave::byteToInt(int* result, char* bytes) {
46 memcpy(&i, bytes, sizeof(int));
53 char* IoTSlave::intToByteArray(int i, char* bytes) {
55 int iInvert = htobe32(i);
56 memcpy(bytes, &iInvert, sizeof(int));
62 void* IoTSlave::getObjectConverted(void* retObj, string object, string objectClass) {
64 // Returning new objects in heap - so we need to delete them afterwards
65 if (objectClass.compare(STRINGCLASS) == 0) {
66 string* retStr = new string(object);
68 } else if (objectClass.compare(INTCLASS) == 0) {
69 int* retInt = new int(atoi(object.c_str()));
71 } else // return NULL if class is not identifiable
78 // Factoring out iteration
79 char* IoTSlave::recvIter(char* recvBuffer, int recvLen) {
81 int bytesReceived = 0; // Bytes read on each recv()
82 int totalBytesReceived = 0; // Total bytes read
84 while (totalBytesReceived < recvLen) {
85 // Receive up to the buffer size bytes from the sender
86 if ((bytesReceived = (socket->recv(recvBuffer, RCVBUFSIZE))) <= 0) {
87 string errMsg = "IoTSlave: Unable to read!";
88 cerr << errMsg << endl;
92 totalBytesReceived += bytesReceived; // Keep tally of total bytes
99 // Factoring out iteration
100 char* IoTSlave::recvFileIter(char* recvBuffer, int recvLen) {
102 int bytesReceived = 0; // Bytes read on each recv()
103 int totalBytesReceived = 0; // Total bytes read
105 while (totalBytesReceived < recvLen) {
106 // Receive up to the buffer size bytes from the sender
107 if ((bytesReceived = (socket->recv(recvBuffer, recvLen))) <= 0) {
108 string errMsg = "IoTSlave: Unable to read!";
109 cerr << errMsg << endl;
113 totalBytesReceived += bytesReceived; // Keep tally of total bytes
120 void IoTSlave::openFile(string fileName) {
122 log.open(FILEPATH + fileName + FILEEXT);
126 void IoTSlave::writeToFile(string logMsg) {
128 log << "IoTSlave: " << logMsg << endl;
132 void IoTSlave::closeFile() {
138 void IoTSlave::getObjectHandler(string objectClassName) {
141 string strObj = FILEPATH + objectClassName + SOEXT;
142 void* handle = dlopen (strObj.c_str(), RTLD_LAZY);
144 fputs (dlerror(), stderr);
145 writeToFile("Error handling object!");
148 writeToFile("Object handled!");
150 string createFunction = CREATEFUNCTION + objectClassName;
151 create_object = (create_t*) dlsym(handle, createFunction.c_str());
152 const char* dlsym_error = dlerror();
154 cerr << "Cannot load symbol create: " << dlsym_error << '\n';
155 writeToFile("Cannot load symbol create!");
158 writeToFile("Object factory created for " + objectClassName);
160 string destroyFunction = DESTROYFUNCTION + objectClassName;
161 destroy_object = (destroy_t*) dlsym(handle, destroyFunction.c_str());
162 dlsym_error = dlerror();
164 cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
165 writeToFile("Cannot load symbol destroy!");
168 writeToFile("Object destroyer created for " + objectClassName);
169 // Create initializer
170 string initFunction = INITFUNCTION + objectClassName;
171 init_object = (init_t*) dlsym(handle, initFunction.c_str());
172 dlsym_error = dlerror();
174 cerr << "Cannot load symbol init: " << dlsym_error << '\n';
175 writeToFile("Cannot load symbol init!");
178 writeToFile("Object initializer created for " + objectClassName);
182 // Run init_object function
183 void IoTSlave::runInitObject(IoTSlave* iotslave) {
185 iotslave->init_object(iotslave->objMainCls);
189 // Instantiate main object!
190 // Use handler obtained by getObjectHandler() and instantiate object!
191 void IoTSlave::instantiateMainObject() {
193 // IoTSet + IoTRelation objects
194 int paramSize = vecIoTSet.size() + vecIoTRel.size();
195 void* params[paramSize];
197 for(int i=0; i<vecIoTSet.size(); i++) {
198 params[j] = vecIoTSet[i]; j++;
200 writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
201 for(int i=0; i<vecIoTRel.size(); i++) {
202 params[j] = vecIoTRel[i]; j++;
204 writeToFile("Vector IoTRelation size: " + to_string(vecIoTRel.size()));
205 objMainCls = create_object(params);
206 writeToFile("Object created for " + mainObjectName);
207 init_object(objMainCls);
208 //thread th1 (&IoTSlave::runInitObject, this, this);
210 //thread th1 (&IoTSlave::runInitObject, this, this);
212 writeToFile("Initialized object " + mainObjectName);
216 // Instantiate driver object!
217 // Use handler obtained by getObjectHandler() and instantiate object!
218 void IoTSlave::instantiateDriverObject() {
220 // IoTDeviceAddress + other arguments
221 int paramSize = vecIoTSet.size() + args.size();
222 void* params[paramSize];
223 for(int i=0; i<vecIoTSet.size(); i++) {
224 params[i] = vecIoTSet[i]; // Just the first object is taken in this case
226 writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
227 writeToFile("Arg size: " + to_string(args.size()));
228 int countArg = vecIoTSet.size(); // Start from after the address set
229 // Iterate over arguments
230 for(int i=0; i<args.size(); i++) {
231 params[countArg] = getObjectConverted(params[countArg], args[i], argClasses[i]);
234 objMainCls = create_object(params);
235 // Delete unused object after conversion and instantiation
236 for(int i=1; i<paramSize; i++) {
237 if (argClasses[i-1].compare(STRINGCLASS) == 0) {
238 delete (string*) params[i];
239 } else if (argClasses[i-1].compare(INTCLASS) == 0)
240 delete (int*) params[i];
242 writeToFile("Object created for " + objectClassName);
246 // Use handler obtained by getObjectHandler() and instantiate skeleton object!
247 void IoTSlave::instantiateSkelObject() {
249 void* params[SKELPARAMSIZE];
250 params[0] = objMainCls;
251 string callbackAddress = LOCALHOST;
252 params[1] = &callbackAddress;
253 params[2] = &objectStubPort;
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] = &hostAddress;
266 string callbackAddress = LOCALHOST;
267 params[2] = &callbackAddress;
273 writeToFile("Stub Object " + objectStubClass + " created for " + objectClassName);
274 objStubCls = create_object(params);
279 string IoTSlave::getServerAddress() {
281 return serverAddress;
285 int IoTSlave::getServerPort() {
291 string IoTSlave::getObjectName() {
297 void IoTSlave::sendInteger(int intSend) {
299 char charInt[sizeof(int)];
300 // Convert int to byte array and fix endianness
301 intToByteArray(intSend, charInt);
302 // Send the length first
303 void* toSend = charInt;
304 socket->send(toSend, sizeof(int));
308 int IoTSlave::recvInteger() {
310 int toBeReceived = sizeof(int);
311 char recvInt[sizeof(int)]; // Normally 4 bytes
313 // Receive and iterate until complete
314 //writeToFile("Receiving Integer! Size: " + to_string(toBeReceived));
315 recvIter(recvInt, toBeReceived);
318 byteToInt(&retVal, recvInt);
324 void IoTSlave::sendString(string strSend) {
326 // Send the length first
327 int strLen = strSend.length();
331 char* chStrSend = new char[strLen];
332 strcpy(chStrSend, strSend.c_str());
333 void* toSend = chStrSend;
334 socket->send(toSend, strLen);
340 string IoTSlave::recvString() {
342 // Get the length of string first
343 int strLen = recvInteger();
344 char* recvStr = new char[strLen];
346 // Receive and iterate until complete
347 //writeToFile("Receiving String! Size: " + to_string(strLen));
348 recvIter(recvStr, strLen);
350 string retVal(recvStr, strLen);
357 // Receive file from IoTMaster
358 void IoTSlave::transferFile() {
360 string fileName = recvFile(); sendAck();
361 //unzipFile(fileName);
365 void IoTSlave::unzipFile(string fileName) {
367 // Unzip file (what we are sending is a zipped file)
368 // TODO: perhaps we need to replace this with libzip or zlib later
369 writeToFile("Unzipping file!");
370 string chmodCmd = FILEPATH + fileName + SHELL;
371 //std::system(chmodCmd.c_str());
372 thread th1 (std::system, chmodCmd.c_str());
374 writeToFile("Finished unzipping file!");
378 string IoTSlave::recvFile() {
380 // Get the length of string first
381 string fileName = recvString(); sendAck();
382 int fileLen = recvInteger(); sendAck();
383 writeToFile("Receiving file " + fileName + " with length " + to_string(fileLen) + " bytes...");
384 char* recvFil = new char[fileLen];
385 // Receive and iterate until complete
386 recvFileIter(recvFil, fileLen);
389 fileStream.open(FILEPATH + fileName);
391 writeToFile("Error opening file: " + FILEPATH + fileName);
394 fileStream.write(recvFil, fileLen);
397 // TODO: Experimental
398 //string chmodCmd = FILEPATH + fileName + SHELL;
399 //execv(chmodCmd.c_str(), 0);
404 // Create a driver object, e.g. LifxLightBulb
405 void IoTSlave::createObject() {
407 writeToFile("Creating a driver object now...");
408 // Receiving object info
409 objectName = recvString(); sendAck();
410 writeToFile("=> Driver object name: " + objectName);
411 objectClassName = recvString(); sendAck();
412 writeToFile("=> Driver object class name: " + objectClassName);
413 objectInterfaceName = recvString(); sendAck();
414 writeToFile("=> Driver object interface name: " + objectInterfaceName);
415 objectSkelClass = recvString(); sendAck();
416 writeToFile("=> Driver object skeleton class name: " + objectSkelClass);
417 objectRegPort = recvInteger(); sendAck();
418 writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
419 objectStubPort = recvInteger(); sendAck();
420 writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
421 int numOfArgs = recvInteger(); sendAck();
422 writeToFile("=> Number of args: " + to_string(numOfArgs));
423 for (int i = 0; i < numOfArgs; i++) {
424 string arg = recvString(); sendAck();
426 writeToFile("==> Got argument: " + arg);
428 for (int i = 0; i < numOfArgs; i++) {
429 string argClass = recvString(); sendAck();
430 argClasses.push_back(argClass);
431 writeToFile("==> Got argument class: " + argClass);
433 // We are just receiving object information here
434 // Instantiation will be done when IoTDeviceAddress has been sent
438 // Create a new IoTSet object to hold objects
439 void IoTSlave::createNewIoTSet() {
441 objectFieldName = recvString(); sendAck();
442 // Instantiating new IoTSet object
443 isetObject = new unordered_set<void*>();
444 writeToFile("Creating new IoTSet for field: " + objectFieldName);
448 // Get IoTDeviceAddress object reference and put it inside IoTSet object
449 void IoTSlave::getDeviceIoTSetObject() {
451 writeToFile("Getting IoTDeviceAddress... ");
452 // Get the IoTDeviceAddress info
453 hostAddress = recvString(); sendAck();
454 writeToFile("=> Host address: " + hostAddress);
455 int sourcePort = recvInteger(); sendAck();
456 writeToFile("=> Source port: " + to_string(sourcePort));
457 int destPort = recvInteger(); sendAck();
458 writeToFile("=> Destination port: " + to_string(destPort));
459 bool sourcePortWildCard = (bool) recvInteger(); sendAck();
460 writeToFile("=> Is source port wild card? " + to_string(sourcePortWildCard));
461 bool destPortWildCard = (bool) recvInteger(); sendAck();
462 writeToFile("=> Is destination port wild card? " + to_string(destPortWildCard));
463 // Create IoTDeviceAddress
464 IoTDeviceAddress* objDeviceAddress = new IoTDeviceAddress(hostAddress, sourcePort, destPort,
465 sourcePortWildCard, destPortWildCard);
466 // Insert it into isetObject!
467 isetObject->insert(objDeviceAddress);
468 writeToFile("=> Inserting IoTDeviceAddress into set...");
469 writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
471 //isDriverObject = true;
475 void IoTSlave::createStub() {
476 // Create Stub object
477 unordered_map<string,void*>::const_iterator itr = mapObjNameStub.find(objectName);
478 if (itr != mapObjNameStub.end()) { // Stub has been created earlier
479 writeToFile("=> Stub has been created! Getting back reference...");
480 objStubCls = itr->second;
481 } else { // Instantiate a new stub and map it
482 writeToFile("=> Stub has not been created! Creating a new stub...");
483 getObjectHandler(objectStubClass);
484 instantiateStubObject();
485 mapObjNameStub.insert(make_pair(objectName,objStubCls));
486 writeToFile("=> Map has: " + to_string(mapObjNameStub.size()) + " members");
487 // vector<int> for ports has been copied - now delete it
493 // Get IoTSet object content reference and put it inside IoTSet object
494 // This is basically the stub objects
495 void IoTSlave::getIoTSetObject() {
497 writeToFile("Getting IoTSet object... ");
498 getIoTSetRelationObject();
500 // Insert it into isetObject!
501 isetObject->insert(objStubCls);
502 writeToFile("=> Inserting stub object into set...");
503 writeToFile("==> Now we have " + to_string(isetObject->size()) + " object(s)!");
507 // Reinitialize IoTSet field!
508 void IoTSlave::reinitializeIoTSetField() {
510 writeToFile("Reinitialize IoTSet field...");
511 iotsetObject = new IoTSet<void*>(isetObject);
512 // Collect IoTSet field first in a vector
513 vecIoTSet.push_back(iotsetObject);
515 // Create object if this is for driver object
516 // Right now we assume that this needs only one object per device
517 /*if (isDriverObject) {
518 // Instantiate driver object
519 getObjectHandler(objectClassName);
520 instantiateDriverObject();
521 // Instantiate skeleton object
522 getObjectHandler(objectSkelClass);
523 instantiateSkelObject();
528 // Instantiate driver object
529 void IoTSlave::createDriverObject() {
531 // Instantiate driver object
532 getObjectHandler(objectClassName);
533 instantiateDriverObject();
534 // Instantiate skeleton object
535 getObjectHandler(objectSkelClass);
536 instantiateSkelObject();
540 // Create a new IoTRelation object to hold objects
541 void IoTSlave::createNewIoTRelation() {
543 objectFieldName = recvString(); sendAck();
544 // Instantiating new IoTSet object
545 irelObject = new unordered_multimap<void*,void*>();
546 writeToFile("Creating new IoTRelation for field: " + objectFieldName);
550 // Get IoTRelation object
551 void IoTSlave::getIoTSetRelationObject() {
553 hostAddress = recvString(); sendAck();
554 writeToFile("=> Host address: " + hostAddress);
555 objectName = recvString(); sendAck();
556 writeToFile("=> Driver object name: " + objectName);
557 objectClassName = recvString(); sendAck();
558 writeToFile("=> Driver object class name: " + objectClassName);
559 objectInterfaceName = recvString(); sendAck();
560 writeToFile("=> Driver object interface name: " + objectInterfaceName);
561 objectStubClass = recvString(); sendAck();
562 writeToFile("=> Driver object stub class name: " + objectStubClass);
563 objectRegPort = recvInteger(); sendAck();
564 writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
565 objectStubPort = recvInteger(); sendAck();
566 writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
567 int numOfPorts = recvInteger(); sendAck();
568 ports = new vector<int>();
569 for (int i = 0; i < numOfPorts; i++) {
570 int port = recvInteger(); sendAck();
571 ports->push_back(port);
572 writeToFile("==> Got a new port: " + to_string(port));
577 // Get the first object of IoTRelation
578 void IoTSlave::getIoTRelationFirstObject() {
580 writeToFile("Getting IoTRelation first object... ");
581 getIoTSetRelationObject();
583 // Hold the first object of IoTRelation
584 irelFirstObject = objStubCls;
585 writeToFile("=> Holding first stub object...");
589 // Get the second object of IoTRelation
590 void IoTSlave::getIoTRelationSecondObject() {
592 writeToFile("Getting IoTRelation second object... ");
593 getIoTSetRelationObject();
595 // Hold the first object of IoTRelation
596 irelSecondObject = objStubCls;
597 writeToFile("=> Holding second stub object...");
598 pair<void*,void*>* iotrelPair = new pair<void*,void*>(irelFirstObject, irelSecondObject);
599 writeToFile("=> Creating a pair of stub objects and inserting into IoTRelation object...");
600 irelObject->insert(*iotrelPair);
604 // Reinitialize IoTRelation
605 void IoTSlave::reinitializeIoTRelationField() {
607 writeToFile("Reinitialize IoTRelation field...");
608 iotrelObject = new IoTRelation<void*,void*>(irelObject);
609 // Collect IoTSet field first in a vector
610 vecIoTRel.push_back(iotrelObject);
614 // Invoke init() method in main controller
615 void IoTSlave::invokeInitMethod() {
617 writeToFile("Invoke init() method for: " + mainObjectName);
618 // Instantiate main controller object
619 getObjectHandler(mainObjectName);
620 instantiateMainObject();
625 // Create a main object, e.g. Lifxtest
626 void IoTSlave::createMainObject() {
628 mainObjectName = recvString(); sendAck();
629 writeToFile("Creating main object: " + mainObjectName);
630 // Just receive the name of the class object here
631 // We will instantiate the object after we get the set/relation objects
635 void IoTSlave::sendAck() {
637 int codeAck = (int) ACKNOWLEDGED;
638 sendInteger(codeAck);
642 bool IoTSlave::recvEndTransfer() {
644 int codeEndTransfer = (int) END_TRANSFER;
645 int recvCode = recvInteger();
646 if (recvCode == codeEndTransfer)
652 void IoTSlave::commIoTMaster() {
654 writeToFile("Starting main loop...");
655 // Main iteration/loop
657 IoTCommCode message = (IoTCommCode) recvInteger();
658 writeToFile("Message: " + to_string(message));
671 case CREATE_MAIN_OBJECT:
675 case CREATE_NEW_IOTSET:
679 case CREATE_NEW_IOTRELATION:
680 createNewIoTRelation();
683 case GET_IOTSET_OBJECT:
687 case GET_IOTRELATION_FIRST_OBJECT:
688 getIoTRelationFirstObject();
691 case GET_IOTRELATION_SECOND_OBJECT:
692 getIoTRelationSecondObject();
695 case REINITIALIZE_IOTSET_FIELD:
696 reinitializeIoTSetField();
699 case REINITIALIZE_IOTRELATION_FIELD:
700 reinitializeIoTRelationField();
703 case GET_DEVICE_IOTSET_OBJECT:
704 getDeviceIoTSetObject();
707 case GET_ZB_DEV_IOTSET_OBJECT:
708 //getZBDevIoTSetObject();
711 case GET_ADD_IOTSET_OBJECT:
712 //getAddIoTSetObject();
715 case INVOKE_INIT_METHOD:
719 case CREATE_DRIVER_OBJECT:
720 createDriverObject();
733 writeToFile("End of loop!");
737 int main(int argc, char *argv[]) {
739 string serverAddress = argv[1];
740 char* servPort = argv[2];
741 int serverPort = atoi(servPort);
742 string strObjName = argv[3];
743 IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort, strObjName);
745 iotSlave->commIoTMaster();