Removing printing statements from C++ RMI library - this will cause SO files to get...
[iot2.git] / iotjava / iotrmi / C++ / IoTRMICall.hpp
1 /** Class IoTRMICall 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 stub part of the RMI
6  *  communication. It bridges and creates RMI requests to be
7  *  transferred into the RMI object.
8  *
9  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
10  * @version     1.0
11  * @since       2016-10-18
12  */
13 #ifndef _IOTRMICALL_HPP__
14 #define _IOTRMICALL_HPP__
15
16 #include <iostream>
17 #include <string>
18 #include <mutex>
19 #include "IoTRMIUtil.hpp"
20 #include "IoTSocketClient.hpp"
21
22 using namespace std;
23
24 mutex mtx;
25
26 class IoTRMICall final {
27         public:
28                 IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult);
29                 ~IoTRMICall();
30                 // Public methods
31                 int             methodLength(string paramCls[], void* paramObj[], int numParam);
32                 char*   methodToBytes(int objectId, int methId, string paramCls[], void* paramObj[],
33                                                                 char* method, int numParam);
34                 void*   remoteCall(int objectId, int methodId, string retType, string paramCls[], 
35                                                                 void* paramObj[], int numParam, void* retObj);
36                 void**  getStructObjects(string retType[], int numRet, void* retObj[]);
37                 void**  getReturnObjects(char* retBytes, string retCls[], int numRet, void* retObj[]);
38
39         private:
40                 IoTRMIUtil                      *rmiUtil;
41                 IoTSocketClient         *rmiClient;
42
43                 // Private methods
44                 void                            getMethodIds(const string methodSign[], const int size);
45 };
46
47
48 // Constructor
49 IoTRMICall::IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult) {
50
51         rmiUtil = new IoTRMIUtil();
52         if (rmiUtil == NULL) {
53                 perror("IoTRMICall: IoTRMIUtil isn't initialized!");
54         }
55         rmiClient = new IoTSocketClient(_port, _address, _rev, _bResult);
56         if (rmiClient == NULL) {
57                 perror("IoTRMICall: IoTSocketClient isn't initialized!");
58         }
59 }
60
61
62 // Destructor
63 IoTRMICall::~IoTRMICall() {
64
65         // Clean up
66         if (rmiUtil != NULL) {
67                 
68                 delete rmiUtil;
69                 rmiUtil = NULL;         
70         }
71         if (rmiClient != NULL) {
72
73                 fflush(NULL);
74                 rmiClient->close();             
75                 delete rmiClient;
76                 rmiClient = NULL;               
77         }
78 }
79
80
81 // Calls a method remotely by passing in parameters and getting a return object
82 void* IoTRMICall::remoteCall(int objectId, int methodId, string retType, string paramCls[], 
83                                                                 void* paramObj[], int numParam, void* retObj) {
84
85         // Critical section that is used by different objects
86         lock_guard<mutex> guard(mtx);
87         // Send input parameters
88         int len = methodLength(paramCls, paramObj, numParam);
89         char method[len];
90         methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
91         // Send bytes
92         fflush(NULL);
93         rmiClient->sendBytes(method, len);
94         fflush(NULL);
95         // Receive return value and return it to caller
96         if (retType.compare("void") == 0)
97                 // Just make it NULL if it's a void return
98                 retObj = NULL;
99         else {
100                 int retLen = 0;
101                 char* retObjBytes = NULL;
102                 retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
103                 retObj = IoTRMIUtil::getParamObject(retObj, retType.c_str(), retObjBytes, retLen);
104                 // Delete received bytes object
105                 delete[] retObjBytes;
106         }
107         
108         return retObj;
109 }
110
111
112 // Get a set of return objects (struct)
113 void** IoTRMICall::getStructObjects(string retType[], int numRet, void* retObj[]) {
114
115         // Critical section that is used by different objects
116         lock_guard<mutex> guard(mtx);
117         // Receive struct return value and return it to caller
118         int retLen = 0;
119         char* retObjBytes = NULL;
120         // Return size of array of struct
121         retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
122         retObj = getReturnObjects(retObjBytes, retType, numRet, retObj);
123         // Delete received bytes object
124         delete[] retObjBytes;
125         
126         return retObj;
127 }
128
129
130 // Find the bytes length of a method
131 int IoTRMICall::methodLength(string paramCls[], void* paramObj[], int numParam) {
132
133         // Get byte arrays and calculate method bytes length
134         // Start from the object Id + method Id...
135         int methodLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
136         for (int i = 0; i < numParam; i++) {
137                 // Find the parameter length
138                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
139                 if (paramLen == -1) { // Store the length of the field - indefinite length
140                         paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
141                         // Some space for param length, i.e. 32 bits for integer                
142                         methodLen = methodLen + IoTRMIUtil::PARAM_LEN;
143                 }
144                 // Calculate methodLen
145                 methodLen = methodLen + paramLen;
146         }
147         return methodLen;
148 }
149
150
151 // Convert method and its parameters into bytes
152 char* IoTRMICall::methodToBytes(int objectId, int methId, string paramCls[], 
153                 void* paramObj[], char* method, int numParam) {
154
155         // Get object Id in bytes
156         char objId[IoTRMIUtil::OBJECT_ID_LEN];
157         IoTRMIUtil::intToByteArray(objectId, objId);
158         memcpy(method, objId, IoTRMIUtil::OBJECT_ID_LEN);
159         int pos = IoTRMIUtil::OBJECT_ID_LEN;
160         // Get method Id in bytes
161         char methodId[IoTRMIUtil::METHOD_ID_LEN];
162         IoTRMIUtil::intToByteArray(methId, methodId);
163         memcpy(method + pos, methodId, IoTRMIUtil::METHOD_ID_LEN);
164         pos = pos + IoTRMIUtil::METHOD_ID_LEN;
165         // Get byte arrays and calculate method bytes length
166         for (int i = 0; i < numParam; i++) {
167                 // Find the parameter length
168                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
169                 if (paramLen == -1) { // Store the length of the field - indefinite length
170                         paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
171                         // Write the parameter length
172                         char prmLenBytes[IoTRMIUtil::PARAM_LEN];
173                         IoTRMIUtil::intToByteArray(paramLen, prmLenBytes);
174                         memcpy(method + pos, prmLenBytes, IoTRMIUtil::PARAM_LEN);                       
175                         pos = pos + IoTRMIUtil::PARAM_LEN;
176                 }
177                 // Get array of bytes and put it in the array of array of bytes
178                 char objBytes[paramLen];
179                 IoTRMIUtil::getObjectBytes(objBytes, paramObj[i], paramCls[i].c_str());
180                 memcpy(method + pos, objBytes, paramLen);
181                 pos = pos + paramLen;
182         }
183
184         return method;
185 }
186
187
188 void** IoTRMICall::getReturnObjects(char* retBytes, string retCls[], int numRet, void* retObj[]) {
189
190         // Byte scanning position
191         int pos = 0;
192         for (int i = 0; i < numRet; i++) {
193                 int retLen = rmiUtil->getTypeSize(retCls[i]);
194                 // Get the 32-bit field in the byte array to get the actual
195                 //              length (this is a param with indefinite length)
196                 if (retLen == -1) {
197                         char bytRetLen[IoTRMIUtil::RETURN_LEN];
198                         memcpy(bytRetLen, retBytes + pos, IoTRMIUtil::RETURN_LEN);
199                         pos = pos + IoTRMIUtil::RETURN_LEN;
200                         int* retLenPtr = IoTRMIUtil::byteArrayToInt(&retLen, bytRetLen);
201                         retLen = *retLenPtr;
202                 }
203                 char retObjBytes[retLen];
204                 memcpy(retObjBytes, retBytes + pos, retLen);
205                 pos = pos + retLen;
206                 retObj[i] = IoTRMIUtil::getParamObject(retObj[i], retCls[i].c_str(), retObjBytes, retLen);
207         }
208
209         return retObj;
210 }
211
212
213 #endif
214
215