Adding support to returning struct/list of struct objects
[iot2.git] / iotjava / iotrmi / C++ / IoTRMIObject.hpp
1 /** Class IoTRMIObject provides methods that the upper
2  *  layers can use to transport and invoke methods
3  *  when using IoTSocket, IoTSocketClient and IoTSocketServer.
4  *  <p>
5  *  This class serves in the skeleton part of the RMI
6  *  communication. It instatiate an RMI object and activate
7  *  a server process that handles RMI requests.
8  *
9  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
10  * @version     1.0
11  * @since       2016-10-24
12  */
13 #ifndef _IOTRMIOBJECT_HPP__
14 #define _IOTRMIOBJECT_HPP__
15
16 #include <iostream>
17 #include <string>
18 #include "IoTRMIUtil.hpp"
19 #include "IoTSocketServer.hpp"
20
21 using namespace std;
22
23 class IoTRMIObject {
24         public:
25                 IoTRMIObject(int _port, bool* _bResult);
26                 ~IoTRMIObject();
27                 // Public methods
28                 void                            sendReturnObj(void* retObj, string type);
29                 void                            sendReturnObj(void* retObj[], string type[], int numRet);
30                 int                                     returnLength(void* retObj[], string retCls[], int numRet);
31                 char*                           returnToBytes(void* retObj[], string retCls[], char* retBytes, int numRet);
32                 char*                           getMethodBytes();
33                 int                                     getMethodBytesLen();
34                 void                            setMethodBytes(char* _methodBytes);
35                 int                                     getObjectId();
36                 static int                      getObjectId(char* methodBytes);
37                 int                                     getMethodId();
38                 void**                          getMethodParams(string paramCls[], int numParam, void* paramObj[]);
39
40         private:
41                 IoTRMIUtil                      *rmiUtil;
42                 IoTSocketServer         *rmiServer;
43                 char*                           methodBytes;
44                 int                                     methodLen;
45
46                 // Private methods
47                 void                            getMethodIds(const string methodSign[], const int size);
48 };
49
50
51 // Constructor
52 IoTRMIObject::IoTRMIObject(int _port, bool* _bResult) {
53
54         rmiUtil = new IoTRMIUtil();
55         if (rmiUtil == NULL) {
56                 perror("IoTRMIObject: IoTRMIUtil isn't initialized!");
57         }
58
59         methodBytes = NULL;
60         methodLen = 0;
61
62         rmiServer = new IoTSocketServer(_port, _bResult);
63         if (rmiServer == NULL) {
64                 perror("IoTRMIObject: IoTSocketServer isn't initialized!");
65         }
66         fflush(NULL);
67         rmiServer->connect();
68         fflush(NULL);
69
70 }
71
72
73 // Destructor
74 IoTRMIObject::~IoTRMIObject() {
75
76         // Clean up
77         if (rmiUtil != NULL) {
78                 
79                 delete rmiUtil;
80                 rmiUtil = NULL;         
81         }
82         if (rmiServer != NULL) {
83
84                 fflush(NULL);
85                 rmiServer->close();     
86                 delete rmiServer;
87                 rmiServer = NULL;               
88         }
89 }
90
91
92 // Send return values in bytes to the caller
93 void IoTRMIObject::sendReturnObj(void* retObj, string type) {
94
95         // Find the length of return object in bytes
96         int retLen = rmiUtil->getTypeSize(type);
97         if (retLen == -1) {
98                 retLen = rmiUtil->getVarTypeSize(type, retObj);
99         }
100         // Need object bytes variable
101         char retObjBytes[retLen];
102         IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
103         rmiServer->sendBytes(retObjBytes, retLen);
104 }
105
106
107 // Send return values in bytes to the caller (for more than one object - struct)
108 void IoTRMIObject::sendReturnObj(void* retObj[], string type[], int numRet) {
109
110         // Find the length of return object in bytes
111         int retLen = returnLength(retObj, type, numRet);
112         // Need object bytes variable
113         char retObjBytes[retLen];
114         returnToBytes(retObj, type, retObjBytes, numRet);
115         IoTRMIUtil::printBytes(retObjBytes, retLen, false);
116         rmiServer->sendBytes(retObjBytes, retLen);
117 }
118
119
120 // Get method bytes from the socket
121 char* IoTRMIObject::getMethodBytes() {
122
123         // Get method in bytes and update method length
124         //fflush(NULL);
125         methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
126         fflush(NULL);
127         return methodBytes;
128 }
129
130
131 // Get method bytes length
132 int IoTRMIObject::getMethodBytesLen() {
133
134         return methodLen;
135 }
136
137
138 // Get object Id from bytes
139 int IoTRMIObject::getObjectId() {
140
141         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
142         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
143         // Get method signature 
144         int objectId = 0;
145         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
146         
147         return objectId;
148 }
149
150
151 // Get object Id from bytes (static version)
152 int IoTRMIObject::getObjectId(char* methodBytes) {
153
154         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
155         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
156         // Get method signature 
157         int objectId = 0;
158         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
159         
160         return objectId;
161 }
162
163
164 // Get methodId
165 int IoTRMIObject::getMethodId() {
166
167         // Get method Id
168         char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
169         memcpy(methodIdBytes, methodBytes + IoTRMIUtil::OBJECT_ID_LEN, IoTRMIUtil::METHOD_ID_LEN);
170         // Get method signature 
171         int methodId = 0;
172         IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
173         
174         return methodId;
175 }
176
177
178 // Get method parameters and return an array of parameter objects
179 //
180 // For primitive objects:
181 // | 32-bit method ID | m-bit actual data (fixed length)  |
182 // 
183 // For string, arrays, and non-primitive objects:
184 // | 32-bit method ID | 32-bit length | n-bit actual data | ...
185 void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
186
187         // Byte scanning position
188         int pos = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
189         for (int i = 0; i < numParam; i++) {
190                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
191                 // Get the 32-bit field in the byte array to get the actual
192                 //              length (this is a param with indefinite length)
193                 if (paramLen == -1) {
194                         char bytPrmLen[IoTRMIUtil::PARAM_LEN];
195                         memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
196                         pos = pos + IoTRMIUtil::PARAM_LEN;
197                         int* prmLenPtr = IoTRMIUtil::byteArrayToInt(&paramLen, bytPrmLen);
198                         paramLen = *prmLenPtr;
199                 }
200                 char paramBytes[paramLen];
201                 memcpy(paramBytes, methodBytes + pos, paramLen);
202                 pos = pos + paramLen;
203                 paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes, paramLen);
204         }
205         // Delete methodBytes
206         delete[] methodBytes;
207
208         return paramObj;
209 }
210
211
212 // Find the bytes length of a return object (struct that has more than 1 member)
213 int     IoTRMIObject::returnLength(void* retObj[], string retCls[], int numRet) {
214
215         // Get byte arrays and calculate return bytes length
216         int returnLen = 0;
217         for (int i = 0; i < numRet; i++) {
218                 // Find the return length
219                 int retObjLen = rmiUtil->getTypeSize(retCls[i]);
220                 if (retObjLen == -1) { // Store the length of the field - indefinite length
221                         retObjLen = rmiUtil->getVarTypeSize(retCls[i], retObj[i]);
222                         // Some space for return length, i.e. 32 bits for integer               
223                         returnLen = returnLen + IoTRMIUtil::RETURN_LEN;
224                 }
225                 // Calculate returnLen
226                 returnLen = returnLen + retObjLen;
227         }
228
229         return returnLen;
230 }
231
232
233 // Convert return object (struct members) into bytes
234 char* IoTRMIObject::returnToBytes(void* retObj[], string retCls[], char* retBytes, int numRet) {
235
236         int pos = 0;
237         // Get byte arrays and calculate return bytes length
238         for (int i = 0; i < numRet; i++) {
239                 // Find the return length
240                 int retObjLen = rmiUtil->getTypeSize(retCls[i]);
241                 if (retObjLen == -1) { // Store the length of the field - indefinite length
242                         retObjLen = rmiUtil->getVarTypeSize(retCls[i], retObj[i]);
243                         // Write the return length
244                         char retLenBytes[IoTRMIUtil::RETURN_LEN];
245                         IoTRMIUtil::intToByteArray(retObjLen, retLenBytes);
246                         memcpy(retBytes + pos, retLenBytes, IoTRMIUtil::RETURN_LEN);                    
247                         pos = pos + IoTRMIUtil::RETURN_LEN;
248                 }
249                 // Get array of bytes and put it in the array of array of bytes
250                 char objBytes[retObjLen];
251                 IoTRMIUtil::getObjectBytes(objBytes, retObj[i], retCls[i].c_str());
252                 memcpy(retBytes + pos, objBytes, retObjLen);
253                 pos = pos + retObjLen;
254         }
255
256         return retBytes;
257 }
258
259
260 #endif
261
262