Modified and tested IoTMaster for IoTSet in C++; completed IoTMaster and IoTSlave...
[iot2.git] / iotjava / iotruntime / cpp / iotslave / IoTSlave.cpp
index 2761fb1d8c63891f2085df7f657f3763dd0baa3f..82e53bd08e9d474ca1452c8e53efe305539398e8 100644 (file)
@@ -96,6 +96,27 @@ char* IoTSlave::recvIter(char* recvBuffer, int recvLen) {
 }
 
 
+// Factoring out iteration
+char* IoTSlave::recvFileIter(char* recvBuffer, int recvLen) {
+
+    int bytesReceived = 0;              // Bytes read on each recv()
+    int totalBytesReceived = 0;         // Total bytes read
+
+       while (totalBytesReceived < recvLen) {
+               // Receive up to the buffer size bytes from the sender
+               if ((bytesReceived = (socket->recv(recvBuffer, recvLen))) <= 0) {
+                       string errMsg = "IoTSlave: Unable to read!";
+                       cerr << errMsg << endl;
+                       writeToFile(errMsg);
+                       exit(1);
+               }
+               totalBytesReceived += bytesReceived;     // Keep tally of total bytes
+       }
+
+       return recvBuffer;
+}
+
+
 void IoTSlave::openFile(string fileName) {
 
        log.open(FILEPATH + fileName + FILEEXT);
@@ -169,13 +190,18 @@ void IoTSlave::runInitObject(IoTSlave* iotslave) {
 // Use handler obtained by getObjectHandler() and instantiate object!
 void IoTSlave::instantiateMainObject() {
 
-       // IoTDeviceAddress + other arguments
-       int paramSize = vecIoTSet.size();
+       // IoTSet + IoTRelation objects
+       int paramSize = vecIoTSet.size() + vecIoTRel.size();
        void* params[paramSize];
+       int j = 0;
        for(int i=0; i<vecIoTSet.size(); i++) {
-               params[i] = vecIoTSet[i];       // Just the first object is taken in this case
+               params[j] = vecIoTSet[i]; j++;
        }
        writeToFile("Vector IoTSet size: " + to_string(vecIoTSet.size()));
+       for(int i=0; i<vecIoTRel.size(); i++) {
+               params[j] = vecIoTRel[i]; j++;
+       }
+       writeToFile("Vector IoTRelation size: " + to_string(vecIoTRel.size()));
        objMainCls = create_object(params);
        writeToFile("Object created for " + mainObjectName);
        init_object(objMainCls);
@@ -314,7 +340,7 @@ string IoTSlave::recvString() {
 
        // Get the length of string first
        int strLen = recvInteger();
-       char* recvStr = new char[strLen];               // Normally 4 bytes
+       char* recvStr = new char[strLen];
 
        // Receive and iterate until complete
        recvIter(recvStr, strLen);
@@ -326,6 +352,53 @@ string IoTSlave::recvString() {
 }
 
 
+// Receive file from IoTMaster
+void IoTSlave::transferFile() {
+
+       string fileName = recvFile(); sendAck();
+       //unzipFile(fileName);
+}
+
+
+void IoTSlave::unzipFile(string fileName) {
+
+       // Unzip file (what we are sending is a zipped file)
+       // TODO: perhaps we need to replace this with libzip or zlib later      
+       writeToFile("Unzipping file!");
+       string chmodCmd = FILEPATH + fileName + SHELL;
+       //std::system(chmodCmd.c_str());
+       thread th1 (std::system, chmodCmd.c_str());
+       th1.detach();
+       writeToFile("Finished unzipping file!");
+}
+
+
+string IoTSlave::recvFile() {
+
+       // Get the length of string first
+       string fileName = recvString(); sendAck();
+       int fileLen = recvInteger(); sendAck();
+       writeToFile("Receiving file " + fileName + " with length " + to_string(fileLen) + " bytes...");
+       char* recvFil = new char[fileLen];
+       // Receive and iterate until complete
+       recvFileIter(recvFil, fileLen);
+       // Write into file
+       ofstream fileStream;
+       fileStream.open(FILEPATH + fileName);
+       if (!fileStream) {
+               writeToFile("Error opening file: " + FILEPATH + fileName);
+               exit(1);
+       }
+       fileStream.write(recvFil, fileLen);
+       delete[] recvFil;
+       fileStream.close();
+       // TODO: Experimental
+       //string chmodCmd = FILEPATH + fileName + SHELL;
+       //execv(chmodCmd.c_str(), 0);
+       return fileName;
+}
+
+
 // Create a driver object, e.g. LifxLightBulb
 void IoTSlave::createObject() {
 
@@ -396,32 +469,7 @@ void IoTSlave::getDeviceIoTSetObject() {
 }
 
 
-// Get IoTSet object content reference and put it inside IoTSet object
-// This is basically the stub objects
-void IoTSlave::getIoTSetObject() {
-
-       writeToFile("Getting IoTSet object... ");
-       // Get the IoTDeviceAddress info
-       hostAddress = recvString(); sendAck();
-       writeToFile("=> Host address: " + hostAddress);
-       objectName = recvString(); sendAck();
-       writeToFile("=> Driver object name: " + objectName);
-       objectClassName = recvString(); sendAck();
-       writeToFile("=> Driver object class name: " + objectClassName);
-       objectInterfaceName = recvString(); sendAck();
-       writeToFile("=> Driver object interface name: " + objectInterfaceName);
-       objectStubClass = recvString(); sendAck();
-       writeToFile("=> Driver object stub class name: " + objectStubClass);
-       objectRegPort = recvInteger(); sendAck();
-       writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
-       objectStubPort = recvInteger(); sendAck();
-       writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
-       int numOfPorts = recvInteger(); sendAck();
-       for (int i = 0; i < numOfPorts; i++) {
-               int port = recvInteger(); sendAck();
-               ports.push_back(port);
-               writeToFile("==> Got a new port: " + to_string(port));
-       }
+void IoTSlave::createStub() {
        // Create Stub object
        unordered_map<string,void*>::const_iterator itr = mapObjNameStub.find(objectName);
        if (itr != mapObjNameStub.end()) {      // Stub has been created earlier
@@ -434,6 +482,16 @@ void IoTSlave::getIoTSetObject() {
                mapObjNameStub.insert(make_pair(objectName,objStubCls));
                writeToFile("=> Map has: " + to_string(mapObjNameStub.size()) + " members");
        }
+}
+
+
+// Get IoTSet object content reference and put it inside IoTSet object
+// This is basically the stub objects
+void IoTSlave::getIoTSetObject() {
+
+       writeToFile("Getting IoTSet object... ");
+       getIoTSetRelationObject();
+       createStub();
        // Insert it into isetObject!
        isetObject->insert(objStubCls);
        writeToFile("=> Inserting stub object into set...");
@@ -450,6 +508,7 @@ void IoTSlave::reinitializeIoTSetField() {
        vecIoTSet.push_back(iotsetObject);
 
        // Create object if this is for driver object
+       // Right now we assume that this needs only one object per device
        if (isDriverObject) {
                // Instantiate driver object
                getObjectHandler(objectClassName);
@@ -461,6 +520,78 @@ void IoTSlave::reinitializeIoTSetField() {
 }
 
 
+// Create a new IoTRelation object to hold objects
+void IoTSlave::createNewIoTRelation() {
+
+       objectFieldName = recvString(); sendAck();
+       // Instantiating new IoTSet object
+       irelObject = new unordered_multimap<void*,void*>();
+       writeToFile("Creating new IoTSet for field: " + objectFieldName);
+}
+
+
+// Get IoTRelation object
+void IoTSlave::getIoTSetRelationObject() {
+
+       hostAddress = recvString(); sendAck();
+       writeToFile("=> Host address: " + hostAddress);
+       objectName = recvString(); sendAck();
+       writeToFile("=> Driver object name: " + objectName);
+       objectClassName = recvString(); sendAck();
+       writeToFile("=> Driver object class name: " + objectClassName);
+       objectInterfaceName = recvString(); sendAck();
+       writeToFile("=> Driver object interface name: " + objectInterfaceName);
+       objectStubClass = recvString(); sendAck();
+       writeToFile("=> Driver object stub class name: " + objectStubClass);
+       objectRegPort = recvInteger(); sendAck();
+       writeToFile("=> Driver object registry port: " + to_string(objectRegPort));
+       objectStubPort = recvInteger(); sendAck();
+       writeToFile("=> Driver object stub port: " + to_string(objectStubPort));
+       int numOfPorts = recvInteger(); sendAck();
+       for (int i = 0; i < numOfPorts; i++) {
+               int port = recvInteger(); sendAck();
+               ports.push_back(port);
+               writeToFile("==> Got a new port: " + to_string(port));
+       }
+}
+
+
+// Get the first object of IoTRelation
+void IoTSlave::getIoTRelationFirstObject() {
+
+       writeToFile("Getting IoTRelation first object... ");
+       getIoTSetRelationObject();
+       createStub();
+       // Hold the first object of IoTRelation
+       irelFirstObject = objStubCls;
+       writeToFile("=> Holding first stub object...");
+}
+
+
+// Get the second object of IoTRelation
+void IoTSlave::getIoTRelationSecondObject() {
+
+       writeToFile("Getting IoTRelation second object... ");
+       getIoTSetRelationObject();
+       createStub();
+       // Hold the first object of IoTRelation
+       irelSecondObject = objStubCls;
+       writeToFile("=> Holding second stub object...");
+       pair<void*,void*>* iotrelPair = new pair<void*,void*>(irelFirstObject, irelSecondObject);
+       irelObject->insert(*iotrelPair);
+}
+
+
+// Reinitialize IoTRelation
+void IoTSlave::reinitializeIoTRelationField() {
+
+       writeToFile("Reinitialize IoTRelation field...");
+       iotrelObject = new IoTRelation<void*,void*>(irelObject);
+       // Collect IoTSet field first in a vector
+       vecIoTRel.push_back(iotrelObject);
+}
+
+
 // Invoke init() method in main controller
 void IoTSlave::invokeInitMethod() {
 
@@ -504,8 +635,9 @@ void IoTSlave::commIoTMaster() {
        writeToFile("Starting main loop...");
        // Main iteration/loop
        while(true) {
-               IoTCommCode message = (IoTCommCode) recvInteger(); sendAck();
-               //writeToFile("Message: " + (int) message);
+               IoTCommCode message = (IoTCommCode) recvInteger(); 
+               writeToFile("Message: " + to_string(message));
+               sendAck();
                
                switch(message) {
 
@@ -514,7 +646,7 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case TRANSFER_FILE:
-                               //transferFile();
+                               transferFile();
                                break;
 
                        case CREATE_MAIN_OBJECT:
@@ -526,7 +658,7 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case CREATE_NEW_IOTRELATION:
-                               //createNewIoTRelation();
+                               createNewIoTRelation();
                                break;
 
                        case GET_IOTSET_OBJECT:
@@ -534,11 +666,11 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case GET_IOTRELATION_FIRST_OBJECT:
-                               //getIoTRelationFirstObject();
+                               getIoTRelationFirstObject();
                                break;
 
                        case GET_IOTRELATION_SECOND_OBJECT:
-                               //getIoTRelationSecondObject();
+                               getIoTRelationSecondObject();
                                break;
 
                        case REINITIALIZE_IOTSET_FIELD:
@@ -546,7 +678,7 @@ void IoTSlave::commIoTMaster() {
                                break;
 
                        case REINITIALIZE_IOTRELATION_FIELD:
-                               //reinitializeIoTRelationField();
+                               reinitializeIoTRelationField();
                                break;
 
                        case GET_DEVICE_IOTSET_OBJECT:
@@ -581,19 +713,6 @@ void IoTSlave::commIoTMaster() {
 
 int main(int argc, char *argv[]) {
 
-       /*string serverAddress = "localhost";
-       int serverPort = 12345;
-       IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort);
-       cout << "Connection established with server!" << endl;
-       int intReceived = iotSlave->recvInteger();
-       cout << "Integer received: " << intReceived << endl;
-       cout << "Integer sent back + 1: " << intReceived++ << endl;
-       iotSlave->sendInteger(intReceived);
-       string strSend = "test sending string";
-       cout << "Sending string: " << strSend << endl;  
-       iotSlave->sendString(strSend);
-       cout << "Received string: " << iotSlave->recvString() << endl;*/
-       
        string serverAddress = argv[1];
        char* servPort = argv[2];
        int serverPort = atoi(servPort);