8e688a3b128319efce9543c6e4e283cb0bb83c6b
[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                 static int                      getMethodId(char* methodBytes);
39                 void**                          getMethodParams(string paramCls[], int numParam, void* paramObj[]);
40
41         private:
42                 IoTRMIUtil                      *rmiUtil;
43                 IoTSocketServer         *rmiServer;
44                 char*                           methodBytes;
45                 int                                     methodLen;
46
47                 // Private methods
48                 void                            getMethodIds(const string methodSign[], const int size);
49 };
50
51
52 // Constructor
53 IoTRMIObject::IoTRMIObject(int _port, bool* _bResult) {
54
55         rmiUtil = new IoTRMIUtil();
56         if (rmiUtil == NULL) {
57                 perror("IoTRMIObject: IoTRMIUtil isn't initialized!");
58         }
59
60         methodBytes = NULL;
61         methodLen = 0;
62
63         rmiServer = new IoTSocketServer(_port, _bResult);
64         if (rmiServer == NULL) {
65                 perror("IoTRMIObject: IoTSocketServer isn't initialized!");
66         }
67         fflush(NULL);
68         rmiServer->connect();
69         fflush(NULL);
70
71 }
72
73
74 // Destructor
75 IoTRMIObject::~IoTRMIObject() {
76
77         // Clean up
78         if (rmiUtil != NULL) {
79                 
80                 delete rmiUtil;
81                 rmiUtil = NULL;         
82         }
83         if (rmiServer != NULL) {
84
85                 fflush(NULL);
86                 rmiServer->close();     
87                 delete rmiServer;
88                 rmiServer = NULL;               
89         }
90 }
91
92
93 // Send return values in bytes to the caller
94 void IoTRMIObject::sendReturnObj(void* retObj, string type) {
95
96         // Find the length of return object in bytes
97         int retLen = rmiUtil->getTypeSize(type);
98         if (retLen == -1) {
99                 retLen = rmiUtil->getVarTypeSize(type, retObj);
100         }
101         // Need object bytes variable
102         char retObjBytes[retLen];
103         IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
104         rmiServer->sendBytes(retObjBytes, retLen);
105 }
106
107
108 // Send return values in bytes to the caller (for more than one object - struct)
109 void IoTRMIObject::sendReturnObj(void* retObj[], string type[], int numRet) {
110
111         // Find the length of return object in bytes
112         int retLen = returnLength(retObj, type, numRet);
113         // Need object bytes variable
114         char retObjBytes[retLen];
115         returnToBytes(retObj, type, retObjBytes, numRet);
116         IoTRMIUtil::printBytes(retObjBytes, retLen, false);
117         rmiServer->sendBytes(retObjBytes, retLen);
118 }
119
120
121 // Get method bytes from the socket
122 char* IoTRMIObject::getMethodBytes() {
123
124         // Get method in bytes and update method length
125         //fflush(NULL);
126         methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
127         fflush(NULL);
128         return methodBytes;
129 }
130
131
132 // Get method bytes length
133 int IoTRMIObject::getMethodBytesLen() {
134
135         return methodLen;
136 }
137
138
139 // Get object Id from bytes
140 int IoTRMIObject::getObjectId() {
141
142         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
143         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
144         // Get method signature 
145         int objectId = 0;
146         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
147         
148         return objectId;
149 }
150
151
152 // Get object Id from bytes (static version)
153 int IoTRMIObject::getObjectId(char* methodBytes) {
154
155         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
156         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
157         // Get method signature 
158         int objectId = 0;
159         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
160         
161         return objectId;
162 }
163
164
165 // Get methodId
166 int IoTRMIObject::getMethodId() {
167
168         // Get method Id
169         char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
170         memcpy(methodIdBytes, methodBytes + IoTRMIUtil::OBJECT_ID_LEN, IoTRMIUtil::METHOD_ID_LEN);
171         // Get method signature 
172         int methodId = 0;
173         IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
174         
175         return methodId;
176 }
177
178
179 // Get methodId from bytes (static version)
180 int IoTRMIObject::getMethodId(char* methodBytes) {
181
182         // Get method Id
183         char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
184         memcpy(methodIdBytes, methodBytes + IoTRMIUtil::OBJECT_ID_LEN, IoTRMIUtil::METHOD_ID_LEN);
185         // Get method signature 
186         int methodId = 0;
187         IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
188         
189         return methodId;
190 }
191
192
193 // Get method parameters and return an array of parameter objects
194 //
195 // For primitive objects:
196 // | 32-bit method ID | m-bit actual data (fixed length)  |
197 // 
198 // For string, arrays, and non-primitive objects:
199 // | 32-bit method ID | 32-bit length | n-bit actual data | ...
200 void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
201
202         // Byte scanning position
203         int pos = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
204         for (int i = 0; i < numParam; i++) {
205                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
206                 // Get the 32-bit field in the byte array to get the actual
207                 //              length (this is a param with indefinite length)
208                 if (paramLen == -1) {
209                         char bytPrmLen[IoTRMIUtil::PARAM_LEN];
210                         memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
211                         pos = pos + IoTRMIUtil::PARAM_LEN;
212                         int* prmLenPtr = IoTRMIUtil::byteArrayToInt(&paramLen, bytPrmLen);
213                         paramLen = *prmLenPtr;
214                 }
215                 char paramBytes[paramLen];
216                 memcpy(paramBytes, methodBytes + pos, paramLen);
217                 pos = pos + paramLen;
218                 paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes, paramLen);
219         }
220         // Delete methodBytes
221         delete[] methodBytes;
222
223         return paramObj;
224 }
225
226
227 // Find the bytes length of a return object (struct that has more than 1 member)
228 int     IoTRMIObject::returnLength(void* retObj[], string retCls[], int numRet) {
229
230         // Get byte arrays and calculate return bytes length
231         int returnLen = 0;
232         for (int i = 0; i < numRet; i++) {
233                 // Find the return length
234                 int retObjLen = rmiUtil->getTypeSize(retCls[i]);
235                 if (retObjLen == -1) { // Store the length of the field - indefinite length
236                         retObjLen = rmiUtil->getVarTypeSize(retCls[i], retObj[i]);
237                         // Some space for return length, i.e. 32 bits for integer               
238                         returnLen = returnLen + IoTRMIUtil::RETURN_LEN;
239                 }
240                 // Calculate returnLen
241                 returnLen = returnLen + retObjLen;
242         }
243
244         return returnLen;
245 }
246
247
248 // Convert return object (struct members) into bytes
249 char* IoTRMIObject::returnToBytes(void* retObj[], string retCls[], char* retBytes, int numRet) {
250
251         int pos = 0;
252         // Get byte arrays and calculate return bytes length
253         for (int i = 0; i < numRet; i++) {
254                 // Find the return length
255                 int retObjLen = rmiUtil->getTypeSize(retCls[i]);
256                 if (retObjLen == -1) { // Store the length of the field - indefinite length
257                         retObjLen = rmiUtil->getVarTypeSize(retCls[i], retObj[i]);
258                         // Write the return length
259                         char retLenBytes[IoTRMIUtil::RETURN_LEN];
260                         IoTRMIUtil::intToByteArray(retObjLen, retLenBytes);
261                         memcpy(retBytes + pos, retLenBytes, IoTRMIUtil::RETURN_LEN);                    
262                         pos = pos + IoTRMIUtil::RETURN_LEN;
263                 }
264                 // Get array of bytes and put it in the array of array of bytes
265                 char objBytes[retObjLen];
266                 IoTRMIUtil::getObjectBytes(objBytes, retObj[i], retCls[i].c_str());
267                 memcpy(retBytes + pos, objBytes, retObjLen);
268                 pos = pos + retObjLen;
269         }
270
271         return retBytes;
272 }
273
274
275 #endif
276
277