Adding stub and skeleton for Lifxtest and LifxLightBulb; Creating build flow for...
[iot2.git] / iotjava / iotruntime / cpp / iotslave / IoTSlave.cpp
1 #include <iostream>
2 #include <fstream>
3
4 #include "IoTSlave.hpp"
5
6 IoTSlave::IoTSlave(string _serverAddress, int _serverPort, string _objectName) {
7
8         serverAddress = _serverAddress;
9         serverPort = _serverPort;
10         objectName = _objectName;
11         socket = new TCPSocket(serverAddress, serverPort);
12         openFile(objectName);
13         writeToFile("IoTSlave object created! Connection established!");
14 }
15
16
17 IoTSlave::~IoTSlave() {
18
19         if (socket != NULL) {
20                 delete socket;
21                 socket = NULL;
22         }
23         closeFile();
24 }
25
26
27 // Private helper functions
28 int* IoTSlave::byteToInt(int* result, char* bytes) {
29
30         int i = 0;
31         memcpy(&i, bytes, sizeof(int));
32         *result = be32toh(i);
33
34         return result;
35 }
36
37
38 char* IoTSlave::intToByteArray(int i, char* bytes) {
39
40         int iInvert = htobe32(i);
41         memcpy(bytes, &iInvert, sizeof(int));
42
43         return bytes;
44 }
45
46
47 void* IoTSlave::getObjectConverted(void* retObj, string object, string objectClass) {
48
49         // Returning new objects in heap - so we need to delete them afterwards
50         if (objectClass.compare(STRINGCLASS) == 0) {
51                 string* retStr = new string(object);
52                 retObj = retStr;
53         } else if (objectClass.compare(INTCLASS) == 0) {
54                 int* retInt = new int(atoi(object.c_str()));
55                 retObj = retInt;
56         } else  // return NULL if class is not identifiable
57                 return NULL;
58
59         return retObj;
60 }
61
62
63 // Factoring out iteration
64 char* IoTSlave::recvIter(char* recvBuffer, int recvLen) {
65
66     int bytesReceived = 0;              // Bytes read on each recv()
67     int totalBytesReceived = 0;         // Total bytes read
68
69         while (totalBytesReceived < recvLen) {
70                 // Receive up to the buffer size bytes from the sender
71                 if ((bytesReceived = (socket->recv(recvBuffer, RCVBUFSIZE))) <= 0) {
72                         string errMsg = "IoTSlave: Unable to read!";
73                         cerr << errMsg << endl;
74                         writeToFile(errMsg);
75                         exit(1);
76                 }
77                 totalBytesReceived += bytesReceived;     // Keep tally of total bytes
78         }
79
80         return recvBuffer;
81 }
82
83
84 void IoTSlave::openFile(string fileName) {
85
86         log.open(FILEPATH + fileName + FILEEXT);
87 }
88
89
90 void IoTSlave::writeToFile(string logMsg) {
91
92         log << "IoTSlave: " << logMsg << endl;
93 }
94
95
96 void IoTSlave::closeFile() {
97
98         log.close();
99 }
100
101
102 void IoTSlave::instantiateObject(string objectClassName) {
103
104         // Object handling
105         string strObj = FILEPATH + objectClassName + SOEXT;
106         void* handle = dlopen (strObj.c_str(), RTLD_LAZY);
107         if (!handle) {
108                 fputs (dlerror(), stderr);
109                 writeToFile("Error handling object!");
110                 exit(1);
111         }
112         writeToFile("Object handled!");
113         // Create handler
114         create_object = (create_t*) dlsym(handle, CREATEFUNCTION.c_str());
115         const char* dlsym_error = dlerror();
116     if (dlsym_error) {
117         cerr << "Cannot load symbol create: " << dlsym_error << '\n';
118                 writeToFile("Cannot load symbol create!");
119         exit(1);
120     }
121         writeToFile("Object factory created for " + objectClassName);
122         // Destroy handler
123     destroy_object = (destroy_t*) dlsym(handle, DESTROYFUNCTION.c_str());
124     dlsym_error = dlerror();
125     if (dlsym_error) {
126         cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
127                 writeToFile("Cannot load symbol destroy!");
128         exit(1);
129     }
130         writeToFile("Object destroyer created for " + objectClassName);
131 }
132
133
134 // Public methods
135 string IoTSlave::getServerAddress() {
136
137         return serverAddress;
138 }
139
140
141 int IoTSlave::getServerPort() {
142
143         return serverPort;
144 }
145
146
147 string IoTSlave::getObjectName() {
148
149         return objectName;
150 }
151
152
153 void IoTSlave::sendInteger(int intSend) {
154
155         char charInt[sizeof(int)];
156         // Convert int to byte array and fix endianness
157         intToByteArray(intSend, charInt);
158         // Send the length first
159         void* toSend = charInt;
160         socket->send(toSend, sizeof(int));
161 }
162
163
164 int IoTSlave::recvInteger() {
165
166         int toBeReceived = sizeof(int);
167         char recvInt[sizeof(int)];                      // Normally 4 bytes
168
169         // Receive and iterate until complete
170         recvIter(recvInt, toBeReceived);
171
172         int retVal = 0;
173         byteToInt(&retVal, recvInt);
174
175         return retVal;
176 }
177
178
179 void IoTSlave::sendString(string strSend) {
180
181         // Send the length first
182         int strLen = strSend.length();
183         sendInteger(strLen);
184
185         // Send the string
186         char* chStrSend = new char[strLen];
187         strcpy(chStrSend, strSend.c_str());
188         void* toSend = chStrSend;
189         socket->send(toSend, strLen);
190         // Avoid memory leak
191         delete[] chStrSend;
192 }
193
194
195 string IoTSlave::recvString() {
196
197         // Get the length of string first
198         int strLen = recvInteger();
199         char* recvStr = new char[strLen];               // Normally 4 bytes
200
201         // Receive and iterate until complete
202         recvIter(recvStr, strLen);
203
204         string retVal(recvStr, strLen);
205         delete[] recvStr;
206
207         return retVal;
208 }
209
210
211 // Create a driver object, e.g. LifxLightBulb
212 void IoTSlave::createObject() {
213
214         writeToFile("Creating a driver object now...");
215         sendAck();
216         // Receiving object info
217         objectName = recvString(); sendAck();
218         writeToFile("Driver object name: " + objectName);
219         objectClassName = recvString(); sendAck();
220         writeToFile("Driver object class name: " + objectClassName);
221         objectInterfaceName = recvString(); sendAck();
222         writeToFile("Driver object interface name: " + objectInterfaceName);
223         objectSkelClass = recvString(); sendAck();
224         writeToFile("Driver object skeleton class name: " + objectSkelClass);
225         objectRegPort = recvInteger(); sendAck();
226         writeToFile("Driver object registry port: " + to_string(objectRegPort));
227         objectStubPort = recvInteger(); sendAck();
228         writeToFile("Driver object stub port: " + to_string(objectStubPort));
229         int numOfArgs = recvInteger(); sendAck();
230         for (int i = 0; i < numOfArgs; i++) {
231                 string arg = recvString(); sendAck();
232                 args.push_back(arg);
233                 writeToFile("Got argument: " + arg);
234         }
235         for (int i = 0; i < numOfArgs; i++) {
236                 string argClass = recvString(); sendAck();
237                 args.push_back(argClass);
238                 writeToFile("Got argument class: " + argClass);
239         }
240         // We are just receiving object information here
241         // Instantiation will be done when IoTDeviceAddress has been sent
242         //instantiateObject(objectClassName);
243 }
244
245
246 void IoTSlave::createNewIoTSet() {
247
248
249 }
250
251
252 void IoTSlave::getDeviceIoTSetObject() {
253
254
255 }
256
257
258 // Create a main object, e.g. Lifxtest
259 void IoTSlave::createMainObject() {
260
261         writeToFile("Creating main object: " + objectName);
262         string mainObject = recvString();
263         sendAck();
264 }
265
266
267 void IoTSlave::sendAck() {
268
269         int codeAck = (int) ACKNOWLEDGED;
270         sendInteger(codeAck);
271 }
272
273
274 bool IoTSlave::recvEndTransfer() {
275
276         int codeEndTransfer = (int) END_TRANSFER;
277         int recvCode = recvInteger();
278         if (recvCode == codeEndTransfer)
279                 return true;
280         return false;
281 }
282
283
284 void IoTSlave::commIoTMaster() {
285
286         writeToFile("Starting main loop...");
287         // Main iteration/loop
288         while(true) {
289                 IoTCommCode message = (IoTCommCode) recvInteger();
290                 //writeToFile("Message: " + (int) message);
291
292                 switch(message) {
293
294                         case CREATE_OBJECT:
295                                 createObject();
296                                 break;
297
298                         case TRANSFER_FILE:
299                                 //transferFile();
300                                 break;
301
302                         case CREATE_MAIN_OBJECT:
303                                 createMainObject();
304                                 break;
305
306                         case CREATE_NEW_IOTSET:
307                                 createNewIoTSet();
308                                 break;
309
310                         case CREATE_NEW_IOTRELATION:
311                                 //createNewIoTRelation();
312                                 break;
313
314                         case GET_IOTSET_OBJECT:
315                                 //getIoTSetObject();
316                                 break;
317
318                         case GET_IOTRELATION_FIRST_OBJECT:
319                                 //getIoTRelationFirstObject();
320                                 break;
321
322                         case GET_IOTRELATION_SECOND_OBJECT:
323                                 //getIoTRelationSecondObject();
324                                 break;
325
326                         case REINITIALIZE_IOTSET_FIELD:
327                                 //reinitializeIoTSetField();
328                                 break;
329
330                         case REINITIALIZE_IOTRELATION_FIELD:
331                                 //reinitializeIoTRelationField();
332                                 break;
333
334                         case GET_DEVICE_IOTSET_OBJECT:
335                                 getDeviceIoTSetObject();
336                                 break;
337
338                         case GET_ZB_DEV_IOTSET_OBJECT:
339                                 //getZBDevIoTSetObject();
340                                 break;
341
342                         case GET_ADD_IOTSET_OBJECT:
343                                 //getAddIoTSetObject();
344                                 break;
345
346                         case INVOKE_INIT_METHOD:
347                                 //invokeInitMethod();
348                                 break;
349
350                         case END_SESSION:
351                                 // END of session
352                                 goto ENDLOOP;
353                                 break;
354
355                         default:
356                                 break;
357                 }
358         }
359         ENDLOOP:
360         writeToFile("End of loop!");
361 }
362
363
364 int main(int argc, char *argv[]) {
365
366         /*string serverAddress = "localhost";
367         int serverPort = 12345;
368         IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort);
369         cout << "Connection established with server!" << endl;
370         int intReceived = iotSlave->recvInteger();
371         cout << "Integer received: " << intReceived << endl;
372         cout << "Integer sent back + 1: " << intReceived++ << endl;
373         iotSlave->sendInteger(intReceived);
374         string strSend = "test sending string";
375         cout << "Sending string: " << strSend << endl;  
376         iotSlave->sendString(strSend);
377         cout << "Received string: " << iotSlave->recvString() << endl;*/
378         
379         string serverAddress = argv[1];
380         char* servPort = argv[2];
381         int serverPort = atoi(servPort);
382         string strObjName = argv[3];
383         IoTSlave *iotSlave = new IoTSlave(serverAddress, serverPort, strObjName);
384         //iotSlave->sendInteger(123455);
385         iotSlave->sendAck();
386         iotSlave->commIoTMaster();
387         
388         return 0;
389 }