Working C++ IoTSlave for both IoTSet and IoTRelation; threading works for C++ LifxLig...
[iot2.git] / iotjava / iotruntime / cpp / iotslave / IoTSlave.cpp
1 #include <iostream>
2 #include <fstream>
3
4 #include "IoTSlave.hpp"
5
6 #include "Lifxtest.cpp"
7
8 IoTSlave::IoTSlave(string _serverAddress, int _serverPort, string _objectName) {
9
10         //isDriverObject = false;               // Default to false
11         serverAddress = _serverAddress;
12         serverPort = _serverPort;
13         objectName = _objectName;
14         socket = new TCPSocket(serverAddress, serverPort);
15         openFile(objectName);
16         writeToFile("IoTSlave object created! Connection established!");
17 }
18
19
20 IoTSlave::~IoTSlave() {
21
22         if (socket != NULL) {
23                 delete socket;
24                 socket = NULL;
25         }
26         /*if (objMainCls != NULL) {
27                 delete objMainCls;
28                 objMainCls = NULL;
29         }
30         if (objSkelCls != NULL) {
31                 delete objSkelCls;
32                 objSkelCls = NULL;
33         }*/
34         for (IoTSet<void*>* iotset : vecIoTSet) {
35                 delete iotset;
36                 iotset = NULL;
37         }
38         closeFile();
39 }
40
41
42 // Private helper functions
43 int* IoTSlave::byteToInt(int* result, char* bytes) {
44
45         int i = 0;
46         memcpy(&i, bytes, sizeof(int));
47         *result = be32toh(i);
48
49         return result;
50 }
51
52
53 char* IoTSlave::intToByteArray(int i, char* bytes) {
54
55         int iInvert = htobe32(i);
56         memcpy(bytes, &iInvert, sizeof(int));
57
58         return bytes;
59 }
60
61
62 void* IoTSlave::getObjectConverted(void* retObj, string object, string objectClass) {
63
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);
67                 retObj = retStr;
68         } else if (objectClass.compare(INTCLASS) == 0) {
69                 int* retInt = new int(atoi(object.c_str()));
70                 retObj = retInt;
71         } else  // return NULL if class is not identifiable
72                 return NULL;
73
74         return retObj;
75 }
76
77
78 // Factoring out iteration
79 char* IoTSlave::recvIter(char* recvBuffer, int recvLen) {
80
81     int bytesReceived = 0;              // Bytes read on each recv()
82     int totalBytesReceived = 0;         // Total bytes read
83
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;
89                         writeToFile(errMsg);
90                         exit(1);
91                 }
92                 totalBytesReceived += bytesReceived;     // Keep tally of total bytes
93         }
94
95         return recvBuffer;
96 }
97
98
99 // Factoring out iteration
100 char* IoTSlave::recvFileIter(char* recvBuffer, int recvLen) {
101
102     int bytesReceived = 0;              // Bytes read on each recv()
103     int totalBytesReceived = 0;         // Total bytes read
104
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;
110                         writeToFile(errMsg);
111                         exit(1);
112                 }
113                 totalBytesReceived += bytesReceived;     // Keep tally of total bytes
114         }
115
116         return recvBuffer;
117 }
118
119
120 void IoTSlave::openFile(string fileName) {
121
122         log.open(FILEPATH + fileName + FILEEXT);
123 }
124
125
126 void IoTSlave::writeToFile(string logMsg) {
127
128         log << "IoTSlave: " << logMsg << endl;
129 }
130
131
132 void IoTSlave::closeFile() {
133
134         log.close();
135 }
136
137
138 void IoTSlave::getObjectHandler(string objectClassName) {
139
140         // Object handling
141         string strObj = FILEPATH + objectClassName + SOEXT;
142         void* handle = dlopen (strObj.c_str(), RTLD_LAZY);
143         if (!handle) {
144                 fputs (dlerror(), stderr);
145                 writeToFile("Error handling object!");
146                 exit(1);
147         }
148         writeToFile("Object handled!");
149         // Create handler
150         string createFunction = CREATEFUNCTION + objectClassName;
151         create_object = (create_t*) dlsym(handle, createFunction.c_str());
152         const char* dlsym_error = dlerror();
153     if (dlsym_error) {
154         cerr << "Cannot load symbol create: " << dlsym_error << '\n';
155                 writeToFile("Cannot load symbol create!");
156         exit(1);
157     }
158         writeToFile("Object factory created for " + objectClassName);
159         // Destroy handler
160         string destroyFunction = DESTROYFUNCTION + objectClassName;
161     destroy_object = (destroy_t*) dlsym(handle, destroyFunction.c_str());
162     dlsym_error = dlerror();
163     if (dlsym_error) {
164         cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
165                 writeToFile("Cannot load symbol destroy!");
166         exit(1);
167     }
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();
173     if (dlsym_error) {
174         cerr << "Cannot load symbol init: " << dlsym_error << '\n';
175                 writeToFile("Cannot load symbol init!");
176         exit(1);
177     }
178         writeToFile("Object initializer created for " + objectClassName);
179 }
180
181
182 // Run init_object function
183 void IoTSlave::runInitObject(IoTSlave* iotslave) {
184
185         iotslave->init_object(iotslave->objMainCls);
186 }
187
188
189 // Instantiate main object!
190 // Use handler obtained by getObjectHandler() and instantiate object!
191 void IoTSlave::instantiateMainObject() {
192
193         // IoTSet + IoTRelation objects
194         int paramSize = vecIoTSet.size() + vecIoTRel.size();
195         void* params[paramSize];
196         int j = 0;
197         for(int i=0; i<vecIoTSet.size(); i++) {
198                 params[j] = vecIoTSet[i]; j++;
199         }
200         writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
201         for(int i=0; i<vecIoTRel.size(); i++) {
202                 params[j] = vecIoTRel[i]; j++;
203         }
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);
209         //th1.detach();
210         //thread th1 (&IoTSlave::runInitObject, this, this);
211         //th1.join();
212         writeToFile("Initialized object " + mainObjectName);
213 }
214
215
216 // Instantiate driver object!
217 // Use handler obtained by getObjectHandler() and instantiate object!
218 void IoTSlave::instantiateDriverObject() {
219
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
225         }
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]);
232                 countArg++; 
233         }
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];
241         }               
242         writeToFile("Object created for " + objectClassName);
243 }
244
245
246 // Use handler obtained by getObjectHandler() and instantiate skeleton object!
247 void IoTSlave::instantiateSkelObject() {
248
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);
257 }
258
259
260 // Use handler obtained by getObjectHandler() and instantiate stub object!
261 void IoTSlave::instantiateStubObject() {
262
263         void* params[STUBPARAMSIZE];
264         params[0] = &objectStubPort;
265         params[1] = &hostAddress;
266         string callbackAddress = LOCALHOST;
267         params[2] = &callbackAddress;
268         int rev = 0;
269         params[3] = &rev;
270         bool result = false;
271         params[4] = &result;
272         params[5] = ports;
273         writeToFile("Stub Object " + objectStubClass + " created for " + objectClassName);
274         objStubCls = create_object(params);
275 }
276
277
278 // Public methods
279 string IoTSlave::getServerAddress() {
280
281         return serverAddress;
282 }
283
284
285 int IoTSlave::getServerPort() {
286
287         return serverPort;
288 }
289
290
291 string IoTSlave::getObjectName() {
292
293         return objectName;
294 }
295
296
297 void IoTSlave::sendInteger(int intSend) {
298
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));
305 }
306
307
308 int IoTSlave::recvInteger() {
309
310         int toBeReceived = sizeof(int);
311         char recvInt[sizeof(int)];                      // Normally 4 bytes
312
313         // Receive and iterate until complete
314         //writeToFile("Receiving Integer! Size: " + to_string(toBeReceived));
315         recvIter(recvInt, toBeReceived);
316
317         int retVal = 0;
318         byteToInt(&retVal, recvInt);
319
320         return retVal;
321 }
322
323
324 void IoTSlave::sendString(string strSend) {
325
326         // Send the length first
327         int strLen = strSend.length();
328         sendInteger(strLen);
329
330         // Send the string
331         char* chStrSend = new char[strLen];
332         strcpy(chStrSend, strSend.c_str());
333         void* toSend = chStrSend;
334         socket->send(toSend, strLen);
335         // Avoid memory leak
336         delete[] chStrSend;
337 }
338
339
340 string IoTSlave::recvString() {
341
342         // Get the length of string first
343         int strLen = recvInteger();
344         char* recvStr = new char[strLen];
345
346         // Receive and iterate until complete
347         //writeToFile("Receiving String! Size: " + to_string(strLen));
348         recvIter(recvStr, strLen);
349
350         string retVal(recvStr, strLen);
351         delete[] recvStr;
352
353         return retVal;
354 }
355
356
357 // Receive file from IoTMaster
358 void IoTSlave::transferFile() {
359
360         string fileName = recvFile(); sendAck();
361         //unzipFile(fileName);
362 }
363
364
365 void IoTSlave::unzipFile(string fileName) {
366
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());
373         th1.detach();
374         writeToFile("Finished unzipping file!");
375 }
376
377
378 string IoTSlave::recvFile() {
379
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);
387         // Write into file
388         ofstream fileStream;
389         fileStream.open(FILEPATH + fileName);
390         if (!fileStream) {
391                 writeToFile("Error opening file: " + FILEPATH + fileName);
392                 exit(1);
393         }
394         fileStream.write(recvFil, fileLen);
395         delete[] recvFil;
396         fileStream.close();
397         // TODO: Experimental
398         //string chmodCmd = FILEPATH + fileName + SHELL;
399         //execv(chmodCmd.c_str(), 0);
400         return fileName;
401 }
402
403
404 // Create a driver object, e.g. LifxLightBulb
405 void IoTSlave::createObject() {
406
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();
425                 args.push_back(arg);
426                 writeToFile("==> Got argument: " + arg);
427         }
428         for (int i = 0; i < numOfArgs; i++) {
429                 string argClass = recvString(); sendAck();
430                 argClasses.push_back(argClass);
431                 writeToFile("==> Got argument class: " + argClass);
432         }
433         // We are just receiving object information here
434         // Instantiation will be done when IoTDeviceAddress has been sent
435 }
436
437
438 // Create a new IoTSet object to hold objects
439 void IoTSlave::createNewIoTSet() {
440
441         objectFieldName = recvString(); sendAck();
442         // Instantiating new IoTSet object
443         isetObject = new unordered_set<void*>();
444         writeToFile("Creating new IoTSet for field: " + objectFieldName);
445 }
446
447
448 // Get IoTDeviceAddress object reference and put it inside IoTSet object
449 void IoTSlave::getDeviceIoTSetObject() {
450
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)!");
470         // Set flag to true;
471         //isDriverObject = true;
472 }
473
474
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
488                 delete ports;
489         }
490 }
491
492
493 // Get IoTSet object content reference and put it inside IoTSet object
494 // This is basically the stub objects
495 void IoTSlave::getIoTSetObject() {
496
497         writeToFile("Getting IoTSet object... ");
498         getIoTSetRelationObject();
499         createStub();
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)!");
504 }
505
506
507 // Reinitialize IoTSet field!
508 void IoTSlave::reinitializeIoTSetField() {
509
510         writeToFile("Reinitialize IoTSet field...");
511         iotsetObject = new IoTSet<void*>(isetObject);
512         // Collect IoTSet field first in a vector
513         vecIoTSet.push_back(iotsetObject);
514
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();
524         }*/
525 }
526
527
528 // Instantiate driver object
529 void IoTSlave::createDriverObject() {
530
531         // Instantiate driver object
532         getObjectHandler(objectClassName);
533         instantiateDriverObject();
534         // Instantiate skeleton object
535         getObjectHandler(objectSkelClass);
536         instantiateSkelObject();
537 }
538
539
540 // Create a new IoTRelation object to hold objects
541 void IoTSlave::createNewIoTRelation() {
542
543         objectFieldName = recvString(); sendAck();
544         // Instantiating new IoTSet object
545         irelObject = new unordered_multimap<void*,void*>();
546         writeToFile("Creating new IoTRelation for field: " + objectFieldName);
547 }
548
549
550 // Get IoTRelation object
551 void IoTSlave::getIoTSetRelationObject() {
552
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));
573         }
574 }
575
576
577 // Get the first object of IoTRelation
578 void IoTSlave::getIoTRelationFirstObject() {
579
580         writeToFile("Getting IoTRelation first object... ");
581         getIoTSetRelationObject();
582         createStub();
583         // Hold the first object of IoTRelation
584         irelFirstObject = objStubCls;
585         writeToFile("=> Holding first stub object...");
586 }
587
588
589 // Get the second object of IoTRelation
590 void IoTSlave::getIoTRelationSecondObject() {
591
592         writeToFile("Getting IoTRelation second object... ");
593         getIoTSetRelationObject();
594         createStub();
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);
601 }
602
603
604 // Reinitialize IoTRelation
605 void IoTSlave::reinitializeIoTRelationField() {
606
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);
611 }
612
613
614 // Invoke init() method in main controller
615 void IoTSlave::invokeInitMethod() {
616
617         writeToFile("Invoke init() method for: " + mainObjectName);
618         // Instantiate main controller object
619         getObjectHandler(mainObjectName);
620         instantiateMainObject();
621
622 }
623
624
625 // Create a main object, e.g. Lifxtest
626 void IoTSlave::createMainObject() {
627
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
632 }
633
634
635 void IoTSlave::sendAck() {
636
637         int codeAck = (int) ACKNOWLEDGED;
638         sendInteger(codeAck);
639 }
640
641
642 bool IoTSlave::recvEndTransfer() {
643
644         int codeEndTransfer = (int) END_TRANSFER;
645         int recvCode = recvInteger();
646         if (recvCode == codeEndTransfer)
647                 return true;
648         return false;
649 }
650
651
652 void IoTSlave::commIoTMaster() {
653
654         writeToFile("Starting main loop...");
655         // Main iteration/loop
656         while(true) {
657                 IoTCommCode message = (IoTCommCode) recvInteger(); 
658                 writeToFile("Message: " + to_string(message));
659                 sendAck();
660                 
661                 switch(message) {
662
663                         case CREATE_OBJECT:
664                                 createObject();
665                                 break;
666
667                         case TRANSFER_FILE:
668                                 transferFile();
669                                 break;
670
671                         case CREATE_MAIN_OBJECT:
672                                 createMainObject();
673                                 break;
674
675                         case CREATE_NEW_IOTSET:
676                                 createNewIoTSet();
677                                 break;
678
679                         case CREATE_NEW_IOTRELATION:
680                                 createNewIoTRelation();
681                                 break;
682
683                         case GET_IOTSET_OBJECT:
684                                 getIoTSetObject();
685                                 break;
686
687                         case GET_IOTRELATION_FIRST_OBJECT:
688                                 getIoTRelationFirstObject();
689                                 break;
690
691                         case GET_IOTRELATION_SECOND_OBJECT:
692                                 getIoTRelationSecondObject();
693                                 break;
694
695                         case REINITIALIZE_IOTSET_FIELD:
696                                 reinitializeIoTSetField();
697                                 break;
698
699                         case REINITIALIZE_IOTRELATION_FIELD:
700                                 reinitializeIoTRelationField();
701                                 break;
702
703                         case GET_DEVICE_IOTSET_OBJECT:
704                                 getDeviceIoTSetObject();
705                                 break;
706
707                         case GET_ZB_DEV_IOTSET_OBJECT:
708                                 //getZBDevIoTSetObject();
709                                 break;
710
711                         case GET_ADD_IOTSET_OBJECT:
712                                 //getAddIoTSetObject();
713                                 break;
714
715                         case INVOKE_INIT_METHOD:
716                                 invokeInitMethod();
717                                 break;
718
719                         case CREATE_DRIVER_OBJECT:
720                                 createDriverObject();
721                                 break;
722
723                         case END_SESSION:
724                                 // END of session
725                                 goto ENDLOOP;
726                                 break;
727
728                         default:
729                                 break;
730                 }
731         }
732         ENDLOOP:
733         writeToFile("End of loop!");
734 }
735
736
737 int main(int argc, char *argv[]) {
738
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);
744         iotSlave->sendAck();
745         iotSlave->commIoTMaster();
746         
747         return 0;
748 }