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