#include <iostream>
#include <string>
+#include <mutex>
#include "IoTRMIUtil.hpp"
#include "IoTSocketClient.hpp"
using namespace std;
-class IoTRMICall {
+mutex mtx;
+
+class IoTRMICall final {
public:
IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult);
~IoTRMICall();
// Public methods
int methodLength(string paramCls[], void* paramObj[], int numParam);
- char* methodToBytes(string methodSign, string paramCls[], void* paramObj[],
+ char* methodToBytes(int objectId, int methId, string paramCls[], void* paramObj[],
char* method, int numParam);
- void* remoteCall(string methodSign, string retType, string paramCls[],
+ void* remoteCall(int objectId, int methodId, string retType, string paramCls[],
void* paramObj[], int numParam, void* retObj);
+ void** getStructObjects(string retType[], int numRet, void* retObj[]);
+ void** getReturnObjects(char* retBytes, string retCls[], int numRet, void* retObj[]);
private:
- IoTRMIUtil *rmiUtil;
- IoTSocketClient *rmiClient;
+ IoTRMIUtil *rmiUtil;
+ IoTSocketClient *rmiClient;
+
+ // Private methods
+ void getMethodIds(const string methodSign[], const int size);
};
// Calls a method remotely by passing in parameters and getting a return object
-void* IoTRMICall::remoteCall(string methodSign, string retType, string paramCls[],
+void* IoTRMICall::remoteCall(int objectId, int methodId, string retType, string paramCls[],
void* paramObj[], int numParam, void* retObj) {
+ // Critical section that is used by different objects
+ lock_guard<mutex> guard(mtx);
// Send input parameters
int len = methodLength(paramCls, paramObj, numParam);
char method[len];
- methodToBytes(methodSign, paramCls, paramObj, method, numParam);
+ methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
// Send bytes
fflush(NULL);
rmiClient->sendBytes(method, len);
char* retObjBytes = NULL;
retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
retObj = IoTRMIUtil::getParamObject(retObj, retType.c_str(), retObjBytes, retLen);
+ // Delete received bytes object
+ delete[] retObjBytes;
}
return retObj;
}
+// Get a set of return objects (struct)
+void** IoTRMICall::getStructObjects(string retType[], int numRet, void* retObj[]) {
+
+ // Critical section that is used by different objects
+ lock_guard<mutex> guard(mtx);
+ // Receive struct return value and return it to caller
+ int retLen = 0;
+ char* retObjBytes = NULL;
+ // Return size of array of struct
+ retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
+ retObj = getReturnObjects(retObjBytes, retType, numRet, retObj);
+ // Delete received bytes object
+ delete[] retObjBytes;
+
+ return retObj;
+}
+
+
// Find the bytes length of a method
int IoTRMICall::methodLength(string paramCls[], void* paramObj[], int numParam) {
// Get byte arrays and calculate method bytes length
- // Start from the method Id...
- int methodLen = IoTRMIUtil::METHOD_ID_LEN;
+ // Start from the object Id + method Id...
+ int methodLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
for (int i = 0; i < numParam; i++) {
// Find the parameter length
int paramLen = rmiUtil->getTypeSize(paramCls[i]);
if (paramLen == -1) { // Store the length of the field - indefinite length
- if (paramCls[i].compare("string") == 0) {
- // Get the length of the string through void* casting to string*
- paramLen = (*(string*)paramObj[i]).length();
- } else if (paramCls[i].compare("string[]") == 0) {
- paramLen = IoTRMIUtil::getByteStringLength(*(vector<string>*) paramObj[i]);
- } else {
- string error = "IoTRMICall: Unrecognizable type: " + paramCls[i];
- throw error;
- }
+ paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
// Some space for param length, i.e. 32 bits for integer
methodLen = methodLen + IoTRMIUtil::PARAM_LEN;
}
// Calculate methodLen
methodLen = methodLen + paramLen;
}
-
return methodLen;
}
// Convert method and its parameters into bytes
-char* IoTRMICall::methodToBytes(string methodSign, string paramCls[],
+char* IoTRMICall::methodToBytes(int objectId, int methId, string paramCls[],
void* paramObj[], char* method, int numParam) {
- // Get method ID in bytes
+ // Get object Id in bytes
+ char objId[IoTRMIUtil::OBJECT_ID_LEN];
+ IoTRMIUtil::intToByteArray(objectId, objId);
+ memcpy(method, objId, IoTRMIUtil::OBJECT_ID_LEN);
+ int pos = IoTRMIUtil::OBJECT_ID_LEN;
+ // Get method Id in bytes
char methodId[IoTRMIUtil::METHOD_ID_LEN];
- IoTRMIUtil::getHashCodeBytes(methodSign, methodId);
- memcpy(method, methodId, IoTRMIUtil::METHOD_ID_LEN);
- int pos = IoTRMIUtil::METHOD_ID_LEN;
+ IoTRMIUtil::intToByteArray(methId, methodId);
+ memcpy(method + pos, methodId, IoTRMIUtil::METHOD_ID_LEN);
+ pos = pos + IoTRMIUtil::METHOD_ID_LEN;
// Get byte arrays and calculate method bytes length
for (int i = 0; i < numParam; i++) {
// Find the parameter length
int paramLen = rmiUtil->getTypeSize(paramCls[i]);
if (paramLen == -1) { // Store the length of the field - indefinite length
- if (paramCls[i].compare("string") == 0) {
- // Get the length of the string through void* casting to string*
- paramLen = (*(string*)paramObj[i]).length();
- } else if (paramCls[i].compare("string[]") == 0) {
- paramLen = IoTRMIUtil::getByteStringLength(*(vector<string>*) paramObj[i]);
- } else {
- string error = "IoTRMICall: Unrecognizable type: " + paramCls[i];
- throw error;
- }
+ paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
// Write the parameter length
- char prmLenBytes[IoTRMIUtil::METHOD_ID_LEN];
+ char prmLenBytes[IoTRMIUtil::PARAM_LEN];
IoTRMIUtil::intToByteArray(paramLen, prmLenBytes);
memcpy(method + pos, prmLenBytes, IoTRMIUtil::PARAM_LEN);
pos = pos + IoTRMIUtil::PARAM_LEN;
}
+void** IoTRMICall::getReturnObjects(char* retBytes, string retCls[], int numRet, void* retObj[]) {
+
+ // Byte scanning position
+ int pos = 0;
+ for (int i = 0; i < numRet; i++) {
+ int retLen = rmiUtil->getTypeSize(retCls[i]);
+ // Get the 32-bit field in the byte array to get the actual
+ // length (this is a param with indefinite length)
+ if (retLen == -1) {
+ char bytRetLen[IoTRMIUtil::RETURN_LEN];
+ memcpy(bytRetLen, retBytes + pos, IoTRMIUtil::RETURN_LEN);
+ pos = pos + IoTRMIUtil::RETURN_LEN;
+ int* retLenPtr = IoTRMIUtil::byteArrayToInt(&retLen, bytRetLen);
+ retLen = *retLenPtr;
+ }
+ char retObjBytes[retLen];
+ memcpy(retObjBytes, retBytes + pos, retLen);
+ pos = pos + retLen;
+ retObj[i] = IoTRMIUtil::getParamObject(retObj[i], retCls[i].c_str(), retObjBytes, retLen);
+ }
+
+ return retObj;
+}
+
+
#endif