Fixing bug for return value from callback in C++ (sendReturnObj is called twice)...
[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, const string _methodSign[], const int _size);
26                 ~IoTRMIObject();
27                 // Public methods
28                 void            sendReturnObj(void* retObj, string type);
29                 char*           getMethodBytes();
30                 int                     getMethodBytesLen();
31                 void            setMethodBytes(char* _methodBytes);
32                 int                     getObjectId();
33                 static int      getObjectId(char* methodBytes);
34                 string          getSignature();
35                 void**          getMethodParams(string paramCls[], int numParam, void* paramObj[]);
36
37         private:
38                 map<int,string>         mapMethodId2Sign;
39                 IoTRMIUtil                      *rmiUtil;
40                 IoTSocketServer         *rmiServer;
41                 char*                           methodBytes;
42                 int                                     methodLen;
43
44                 // Private methods
45                 void                            getMethodIds(const string methodSign[], const int size);
46 };
47
48
49 // Constructor
50 IoTRMIObject::IoTRMIObject(int _port, bool* _bResult, const string _methodSign[], const int _size) {
51
52         rmiUtil = new IoTRMIUtil();
53         if (rmiUtil == NULL) {
54                 perror("IoTRMIObject: IoTRMIUtil isn't initialized!");
55         }
56
57         methodBytes = NULL;
58         methodLen = 0;
59         getMethodIds(_methodSign, _size);
60
61         rmiServer = new IoTSocketServer(_port, _bResult);
62         if (rmiServer == NULL) {
63                 perror("IoTRMIObject: IoTSocketServer isn't initialized!");
64         }
65         fflush(NULL);
66         rmiServer->connect();
67         fflush(NULL);
68 }
69
70
71 // Destructor
72 IoTRMIObject::~IoTRMIObject() {
73
74         // Clean up
75         if (rmiUtil != NULL) {
76                 
77                 delete rmiUtil;
78                 rmiUtil = NULL;         
79         }
80         if (rmiServer != NULL) {
81
82                 fflush(NULL);
83                 rmiServer->close();     
84                 delete rmiServer;
85                 rmiServer = NULL;               
86         }
87 }
88
89
90 // Send return values in bytes to the caller
91 void IoTRMIObject::sendReturnObj(void* retObj, string type) {
92
93         // Find the length of return object in bytes
94         int retLen = rmiUtil->getTypeSize(type);
95         if (retLen == -1) {
96                 retLen = rmiUtil->getVarTypeSize(type, retObj);
97         }
98         // Need object bytes variable
99         char retObjBytes[retLen];
100         IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
101         rmiServer->sendBytes(retObjBytes, retLen);
102 }
103
104
105 // Get method bytes from the socket
106 char* IoTRMIObject::getMethodBytes() {
107
108         // Get method in bytes and update method length
109         //fflush(NULL);
110         methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
111         fflush(NULL);
112         return methodBytes;
113 }
114
115
116 // Get method bytes length
117 int IoTRMIObject::getMethodBytesLen() {
118
119         return methodLen;
120 }
121
122
123 // Get object Id from bytes
124 int IoTRMIObject::getObjectId() {
125
126         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
127         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
128         // Get method signature 
129         int objectId = 0;
130         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
131         
132         return objectId;
133 }
134
135
136 // Get object Id from bytes (static version)
137 int IoTRMIObject::getObjectId(char* methodBytes) {
138
139         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
140         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
141         // Get method signature 
142         int objectId = 0;
143         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
144         
145         return objectId;
146 }
147
148
149 // Set method bytes
150 void IoTRMIObject::setMethodBytes(char* _methodBytes) {
151
152         // Set method bytes
153         methodBytes = _methodBytes;
154 }
155
156
157 // Get signature from the method-Id-to-method-signature map
158 string IoTRMIObject::getSignature() {
159
160         // Get method Id
161         char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
162         memcpy(methodIdBytes, methodBytes + IoTRMIUtil::OBJECT_ID_LEN, IoTRMIUtil::METHOD_ID_LEN);
163         // Get method signature 
164         int methodId = 0;
165         IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
166         
167         return mapMethodId2Sign.find(methodId)->second;
168 }
169
170
171 // Get method parameters and return an array of parameter objects
172 //
173 // For primitive objects:
174 // | 32-bit method ID | m-bit actual data (fixed length)  |
175 // 
176 // For string, arrays, and non-primitive objects:
177 // | 32-bit method ID | 32-bit length | n-bit actual data | ...
178 void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
179
180         // Byte scanning position
181         int pos = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
182         for (int i = 0; i < numParam; i++) {
183                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
184                 // Get the 32-bit field in the byte array to get the actual
185                 //              length (this is a param with indefinite length)
186                 if (paramLen == -1) {
187                         char bytPrmLen[IoTRMIUtil::PARAM_LEN];
188                         memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
189                         pos = pos + IoTRMIUtil::PARAM_LEN;
190                         int* prmLenPtr = IoTRMIUtil::byteArrayToInt(&paramLen, bytPrmLen);
191                         paramLen = *prmLenPtr;
192                 }
193                 char paramBytes[paramLen];
194                 memcpy(paramBytes, methodBytes + pos, paramLen);
195                 pos = pos + paramLen;
196                 paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes, paramLen);
197         }
198         // Delete methodBytes
199         delete[] methodBytes;
200
201         return paramObj;
202 }
203
204
205 // *************
206 //    Helpers
207 // *************
208 void IoTRMIObject::getMethodIds(const string methodSign[], const int size) {
209
210         for(int i = 0; i < size; i++) {
211                 mapMethodId2Sign[i] = methodSign[i];
212         }
213 }
214
215
216 #endif
217
218