Adding callback for C++ (still has bug for return values); adding struct as method...
[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         cout << "Got into getMethodBytes()" << endl;
110         //fflush(NULL);
111         methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
112         cout << "Got into getMethodBytes() 2" << endl;
113         fflush(NULL);
114         return methodBytes;
115 }
116
117
118 // Get method bytes length
119 int IoTRMIObject::getMethodBytesLen() {
120
121         return methodLen;
122 }
123
124
125 // Get object Id from bytes
126 int IoTRMIObject::getObjectId() {
127
128         char objectIdBytes[IoTRMIUtil::OBJECT_ID_LEN];
129         memcpy(objectIdBytes, methodBytes, IoTRMIUtil::OBJECT_ID_LEN);
130         // Get method signature 
131         int objectId = 0;
132         IoTRMIUtil::byteArrayToInt(&objectId, objectIdBytes);
133         
134         return objectId;
135 }
136
137
138 // Get object Id from bytes (static version)
139 int IoTRMIObject::getObjectId(char* methodBytes) {
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 // Set method bytes
152 void IoTRMIObject::setMethodBytes(char* _methodBytes) {
153
154         // Set method bytes
155         methodBytes = _methodBytes;
156 }
157
158
159 // Get signature from the method-Id-to-method-signature map
160 string IoTRMIObject::getSignature() {
161
162         // Get method Id
163         char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
164         memcpy(methodIdBytes, methodBytes + IoTRMIUtil::OBJECT_ID_LEN, IoTRMIUtil::METHOD_ID_LEN);
165         // Get method signature 
166         int methodId = 0;
167         IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
168         
169         return mapMethodId2Sign.find(methodId)->second;
170 }
171
172
173 // Get method parameters and return an array of parameter objects
174 //
175 // For primitive objects:
176 // | 32-bit method ID | m-bit actual data (fixed length)  |
177 // 
178 // For string, arrays, and non-primitive objects:
179 // | 32-bit method ID | 32-bit length | n-bit actual data | ...
180 void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
181
182         // Byte scanning position
183         int pos = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
184         for (int i = 0; i < numParam; i++) {
185                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
186                 // Get the 32-bit field in the byte array to get the actual
187                 //              length (this is a param with indefinite length)
188                 if (paramLen == -1) {
189                         char bytPrmLen[IoTRMIUtil::PARAM_LEN];
190                         memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
191                         pos = pos + IoTRMIUtil::PARAM_LEN;
192                         int* prmLenPtr = IoTRMIUtil::byteArrayToInt(&paramLen, bytPrmLen);
193                         paramLen = *prmLenPtr;
194                 }
195                 char paramBytes[paramLen];
196                 memcpy(paramBytes, methodBytes + pos, paramLen);
197                 pos = pos + paramLen;
198                 paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes, paramLen);
199         }
200         // Delete methodBytes
201         delete[] methodBytes;
202
203         return paramObj;
204 }
205
206
207 // *************
208 //    Helpers
209 // *************
210 void IoTRMIObject::getMethodIds(const string methodSign[], const int size) {
211
212         for(int i = 0; i < size; i++) {
213                 mapMethodId2Sign[i] = methodSign[i];
214         }
215 }
216
217
218 #endif
219
220