1 /** Class IoTRMICall provides methods that the upper
2 * layers can use to transport and invoke methods
3 * when using IoTSocket, IoTSocketClient and IoTSocketServer.
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.
9 * @author Rahmadi Trimananda <rtrimana @ uci.edu>
13 #ifndef _IOTRMICALL_HPP__
14 #define _IOTRMICALL_HPP__
19 #include "IoTRMIUtil.hpp"
20 #include "IoTSocketClient.hpp"
28 IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult);
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[]);
40 map<string,int> mapSign2MethodId;
42 IoTSocketClient *rmiClient;
45 void getMethodIds(const string methodSign[], const int size);
50 IoTRMICall::IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult) {
52 rmiUtil = new IoTRMIUtil();
53 if (rmiUtil == NULL) {
54 perror("IoTRMICall: IoTRMIUtil isn't initialized!");
56 rmiClient = new IoTSocketClient(_port, _address, _rev, _bResult);
57 if (rmiClient == NULL) {
58 perror("IoTRMICall: IoTSocketClient isn't initialized!");
64 IoTRMICall::~IoTRMICall() {
67 if (rmiUtil != NULL) {
72 if (rmiClient != NULL) {
82 // Calls a method remotely by passing in parameters and getting a return object
83 void* IoTRMICall::remoteCall(int objectId, int methodId, string retType, string paramCls[],
84 void* paramObj[], int numParam, void* retObj) {
86 // Critical section that is used by different objects
87 lock_guard<mutex> guard(mtx);
88 // Send input parameters
89 int len = methodLength(paramCls, paramObj, numParam);
91 methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
94 cout << "Length: " << len << endl;
95 IoTRMIUtil::printBytes(method, len, false);
96 rmiClient->sendBytes(method, len);
98 // Receive return value and return it to caller
99 if (retType.compare("void") == 0)
100 // Just make it NULL if it's a void return
104 char* retObjBytes = NULL;
105 retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
106 retObj = IoTRMIUtil::getParamObject(retObj, retType.c_str(), retObjBytes, retLen);
107 // Delete received bytes object
108 delete[] retObjBytes;
115 // Get a set of return objects (struct)
116 void** IoTRMICall::getStructObjects(string retType[], int numRet, void* retObj[]) {
118 // Critical section that is used by different objects
119 lock_guard<mutex> guard(mtx);
120 // Receive struct return value and return it to caller
122 char* retObjBytes = NULL;
123 // Return size of array of struct
124 retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
125 retObj = getReturnObjects(retObjBytes, retType, numRet, retObj);
126 // Delete received bytes object
127 delete[] retObjBytes;
133 // Find the bytes length of a method
134 int IoTRMICall::methodLength(string paramCls[], void* paramObj[], int numParam) {
136 // Get byte arrays and calculate method bytes length
137 // Start from the object Id + method Id...
138 int methodLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
139 for (int i = 0; i < numParam; i++) {
140 // Find the parameter length
141 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
142 if (paramLen == -1) { // Store the length of the field - indefinite length
143 paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
144 // Some space for param length, i.e. 32 bits for integer
145 methodLen = methodLen + IoTRMIUtil::PARAM_LEN;
147 // Calculate methodLen
148 methodLen = methodLen + paramLen;
154 // Convert method and its parameters into bytes
155 char* IoTRMICall::methodToBytes(int objectId, int methId, string paramCls[],
156 void* paramObj[], char* method, int numParam) {
158 // Get object Id in bytes
159 char objId[IoTRMIUtil::OBJECT_ID_LEN];
160 IoTRMIUtil::intToByteArray(objectId, objId);
161 memcpy(method, objId, IoTRMIUtil::OBJECT_ID_LEN);
162 int pos = IoTRMIUtil::OBJECT_ID_LEN;
163 // Get method Id in bytes
164 char methodId[IoTRMIUtil::METHOD_ID_LEN];
165 IoTRMIUtil::intToByteArray(methId, methodId);
166 memcpy(method + pos, methodId, IoTRMIUtil::METHOD_ID_LEN);
167 pos = pos + IoTRMIUtil::METHOD_ID_LEN;
168 // Get byte arrays and calculate method bytes length
169 for (int i = 0; i < numParam; i++) {
170 // Find the parameter length
171 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
172 if (paramLen == -1) { // Store the length of the field - indefinite length
173 paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
174 // Write the parameter length
175 char prmLenBytes[IoTRMIUtil::PARAM_LEN];
176 IoTRMIUtil::intToByteArray(paramLen, prmLenBytes);
177 memcpy(method + pos, prmLenBytes, IoTRMIUtil::PARAM_LEN);
178 pos = pos + IoTRMIUtil::PARAM_LEN;
180 // Get array of bytes and put it in the array of array of bytes
181 char objBytes[paramLen];
182 IoTRMIUtil::getObjectBytes(objBytes, paramObj[i], paramCls[i].c_str());
183 memcpy(method + pos, objBytes, paramLen);
184 pos = pos + paramLen;
191 void** IoTRMICall::getReturnObjects(char* retBytes, string retCls[], int numRet, void* retObj[]) {
193 // Byte scanning position
195 for (int i = 0; i < numRet; i++) {
196 int retLen = rmiUtil->getTypeSize(retCls[i]);
197 // Get the 32-bit field in the byte array to get the actual
198 // length (this is a param with indefinite length)
200 char bytRetLen[IoTRMIUtil::RETURN_LEN];
201 memcpy(bytRetLen, retBytes + pos, IoTRMIUtil::RETURN_LEN);
202 pos = pos + IoTRMIUtil::RETURN_LEN;
203 int* retLenPtr = IoTRMIUtil::byteArrayToInt(&retLen, bytRetLen);
206 char retObjBytes[retLen];
207 memcpy(retObjBytes, retBytes + pos, retLen);
209 retObj[i] = IoTRMIUtil::getParamObject(retObj[i], retCls[i].c_str(), retObjBytes, retLen);