PHONY += rmi
rmi:
mkdir -p $(BIN_DIR)
-# $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java
-# $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/sample/*.java
+ $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java
+ $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/sample/*.java
# mkdir -p $(BIN_DIR)/iotrmi/C++
#$(G++) iotrmi/C++/IoTSocketServer.cpp -o $(BIN_DIR)/iotrmi/C++/IoTSocketServer.out
#$(G++) iotrmi/C++/IoTSocketClient.cpp -o $(BIN_DIR)/iotrmi/C++/IoTSocketClient.out
# $(G++) iotrmi/C++/sample/CallBack_Stub.cpp -o $(BIN_DIR)/iotrmi/C++/sample/CallBack_Stub.out --std=c++11
# $(G++) iotrmi/C++/sample/CallBack_Skeleton.cpp -o $(BIN_DIR)/iotrmi/C++/sample/CallBack_Skeleton.out --std=c++11
#$(G++) iotrmi/C++/sample/TestClass.cpp -o $(BIN_DIR)/iotrmi/C++/sample/TestClass.out --std=c++11
- $(G++) iotrmi/C++/sample/TestClass_Stub.cpp -o $(BIN_DIR)/iotrmi/C++/sample/TestClass_Stub.out --std=c++11 -pthread -pg
- $(G++) iotrmi/C++/sample/TestClass_Skeleton.cpp -o $(BIN_DIR)/iotrmi/C++/sample/TestClass_Skeleton.out --std=c++11 -pthread -pg
+# $(G++) iotrmi/C++/sample/TestClass_Stub.cpp -o $(BIN_DIR)/iotrmi/C++/sample/TestClass_Stub.out --std=c++11 -pthread -pg
+# $(G++) iotrmi/C++/sample/TestClass_Skeleton.cpp -o $(BIN_DIR)/iotrmi/C++/sample/TestClass_Skeleton.out --std=c++11 -pthread -pg
#$(G++) iotrmi/C++/sample/Test.cpp -o ../bin/iotrmi/C++/sample/Test.out --std=c++11 -lpthread
#$(G++) iotrmi/C++/sample/Test2.cpp -o ../bin/iotrmi/C++/sample/Test2.out --std=c++11 -pthread -pg
# $(G++) iotrmi/C++/sample/StructC.cpp -o ../bin/iotrmi/C++/sample/StructC.out --std=c++11
char* method, int numParam);
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:
map<string,int> mapSign2MethodId;
int len = methodLength(paramCls, paramObj, numParam);
char method[len];
methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
-// IoTRMIUtil::printBytes(method, len, false);
// Send bytes
fflush(NULL);
rmiClient->sendBytes(method, len);
int retLen = 0;
char* retObjBytes = NULL;
retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
-// IoTRMIUtil::printBytes(retObjBytes, retLen, false);
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) {
if (paramLen == -1) { // Store the length of the field - indefinite length
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;
return method;
}
+
+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
IoTRMIObject(int _port, bool* _bResult);
~IoTRMIObject();
// Public methods
- void sendReturnObj(void* retObj, string type);
- char* getMethodBytes();
- int getMethodBytesLen();
- void setMethodBytes(char* _methodBytes);
- int getObjectId();
- static int getObjectId(char* methodBytes);
- int getMethodId();
- void** getMethodParams(string paramCls[], int numParam, void* paramObj[]);
+ void sendReturnObj(void* retObj, string type);
+ void sendReturnObj(void* retObj[], string type[], int numRet);
+ int returnLength(void* retObj[], string retCls[], int numRet);
+ char* returnToBytes(void* retObj[], string retCls[], char* retBytes, int numRet);
+ char* getMethodBytes();
+ int getMethodBytesLen();
+ void setMethodBytes(char* _methodBytes);
+ int getObjectId();
+ static int getObjectId(char* methodBytes);
+ int getMethodId();
+ void** getMethodParams(string paramCls[], int numParam, void* paramObj[]);
private:
- //map<int,string> mapMethodId2Sign;
IoTRMIUtil *rmiUtil;
IoTSocketServer *rmiServer;
char* methodBytes;
methodBytes = NULL;
methodLen = 0;
- //getMethodIds(_methodSign, _size);
rmiServer = new IoTSocketServer(_port, _bResult);
if (rmiServer == NULL) {
fflush(NULL);
rmiServer->connect();
fflush(NULL);
+
}
}
+// Send return values in bytes to the caller (for more than one object - struct)
+void IoTRMIObject::sendReturnObj(void* retObj[], string type[], int numRet) {
+
+ // Find the length of return object in bytes
+ int retLen = returnLength(retObj, type, numRet);
+ // Need object bytes variable
+ char retObjBytes[retLen];
+ returnToBytes(retObj, type, retObjBytes, numRet);
+ IoTRMIUtil::printBytes(retObjBytes, retLen, false);
+ rmiServer->sendBytes(retObjBytes, retLen);
+}
+
+
// Get method bytes from the socket
char* IoTRMIObject::getMethodBytes() {
}
-// Set method bytes
-/*void IoTRMIObject::setMethodBytes(char* _methodBytes) {
-
- // Set method bytes
- methodBytes = _methodBytes;
-}*/
-
-
// Get methodId
int IoTRMIObject::getMethodId() {
}
+// Find the bytes length of a return object (struct that has more than 1 member)
+int IoTRMIObject::returnLength(void* retObj[], string retCls[], int numRet) {
+
+ // Get byte arrays and calculate return bytes length
+ int returnLen = 0;
+ for (int i = 0; i < numRet; i++) {
+ // Find the return length
+ int retObjLen = rmiUtil->getTypeSize(retCls[i]);
+ if (retObjLen == -1) { // Store the length of the field - indefinite length
+ retObjLen = rmiUtil->getVarTypeSize(retCls[i], retObj[i]);
+ // Some space for return length, i.e. 32 bits for integer
+ returnLen = returnLen + IoTRMIUtil::RETURN_LEN;
+ }
+ // Calculate returnLen
+ returnLen = returnLen + retObjLen;
+ }
+
+ return returnLen;
+}
+
+
+// Convert return object (struct members) into bytes
+char* IoTRMIObject::returnToBytes(void* retObj[], string retCls[], char* retBytes, int numRet) {
+
+ int pos = 0;
+ // Get byte arrays and calculate return bytes length
+ for (int i = 0; i < numRet; i++) {
+ // Find the return length
+ int retObjLen = rmiUtil->getTypeSize(retCls[i]);
+ if (retObjLen == -1) { // Store the length of the field - indefinite length
+ retObjLen = rmiUtil->getVarTypeSize(retCls[i], retObj[i]);
+ // Write the return length
+ char retLenBytes[IoTRMIUtil::RETURN_LEN];
+ IoTRMIUtil::intToByteArray(retObjLen, retLenBytes);
+ memcpy(retBytes + pos, retLenBytes, IoTRMIUtil::RETURN_LEN);
+ pos = pos + IoTRMIUtil::RETURN_LEN;
+ }
+ // Get array of bytes and put it in the array of array of bytes
+ char objBytes[retObjLen];
+ IoTRMIUtil::getObjectBytes(objBytes, retObj[i], retCls[i].c_str());
+ memcpy(retBytes + pos, objBytes, retObjLen);
+ pos = pos + retObjLen;
+ }
+
+ return retBytes;
+}
+
+
#endif
const static int OBJECT_ID_LEN = 4; // 4 bytes = 32 bits
const static int METHOD_ID_LEN = 4; // 4 bytes = 32 bits
const static int PARAM_LEN = 4; // 4 bytes = 32 bits (4-byte field that stores the length of the param)
+ const static int RETURN_LEN = 4; // 4 bytes = 32 bits (4-byte field that stores the length of the return object)
const static int CHAR_LEN = 2; // 2 bytes (we follow Java convention)
const static int BOOL_LEN = 1; // 1 byte
void registerCallback(CallBackInterface* _cb);
void registerCallback(vector<CallBackInterface*> _cb);
int callBack();
- void handleStruct(vector<data> vecData);
+ vector<data> handleStruct(vector<data> vecData);
vector<EnumC> handleEnum(vector<EnumC> vecEn);
void thread1();
}
-void TestClass::handleStruct(vector<data> vecData) {
+vector<data> TestClass::handleStruct(vector<data> vecData) {
for (data dat : vecData) {
cout << "Value: " << dat.value << endl;
cout << "Year: " << dat.year << endl;
}
+ data newData;
+ newData.name = "Anonymous";
+ newData.value = 1.33;
+ newData.year = 2016;
+ vecData.push_back(newData);
+
+ return vecData;
}
int TestClass::callBack() {
- /*int sum = 0;
+ int sum = 0;
for (CallBackInterface* cb : cbvec) {
sum = sum + cb->printInt();
}
- return sum;*/
- thread th1 (&TestClass::thread1, this);
+ return sum;
+/* thread th1 (&TestClass::thread1, this);
thread th2 (&TestClass::thread2, this);
th1.join();
th2.join();
- return 1;
+ return 1;*/
}
#endif
virtual void registerCallback(CallBackInterface* _cb) = 0;
virtual void registerCallback(vector<CallBackInterface*> _cb) = 0;
virtual int callBack() = 0;
- virtual void handleStruct(vector<data> vecData) = 0;
+ virtual vector<data> handleStruct(vector<data> vecData) = 0;
virtual vector<EnumC> handleEnum(vector<EnumC> vecEn) = 0;
};
void registerCallback(CallBackInterface* _cb);
void registerCallback(vector<CallBackInterface*> _cb);
int callBack();
- void handleStruct(vector<data> vecData);
+ vector<data> handleStruct(vector<data> vecData);
vector<EnumC> handleEnum(vector<EnumC> vecEn);
void ___setA();
rmiObj->getMethodParams(paramCls, numParam, paramObj);
// Instantiate IoTRMICall object
bool bResult = false;
+ cout << "Port: " << param1 << endl;
+ cout << "Address: " << param2 << endl;
+
rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult);
}
}
-void TestClass_Skeleton::handleStruct(vector<data> vecData) {
+vector<data> TestClass_Skeleton::handleStruct(vector<data> vecData) {
- tc->handleStruct(vecData);
+ return tc->handleStruct(vecData);
}
dat[i].value = param2[i];
dat[i].year = param3[i];
}
- handleStruct(dat);
+ // This is a return value of type vector of struct
+ // If no return value, then just "handleStruct(dat)"
+ vector<data> retData = handleStruct(dat);
+ // Send the length first!
+ int retLength = retData.size();
+ void* retObj = &retLength;
+ rmiObj->sendReturnObj(retObj, "int");
+ // Send the actual bytes - struct of 3 members
+ int numRetObj = 3*retLength;
+ string retCls[numRetObj];
+ void* retObj2[numRetObj];
+ pos = 0;
+ for(int i = 0; i < retLength; i++) {
+ retCls[pos] = "string";
+ retObj2[pos] = &retData[i].name; pos++;
+ retCls[pos] = "float";
+ retObj2[pos] = &retData[i].value; pos++;
+ retCls[pos] = "int";
+ retObj2[pos] = &retData[i].year; pos++;
+ }
+ rmiObj->sendReturnObj(retObj2, retCls, numRetObj);
}
cout << "Return value: " << tcStub->sumArray(input) << endl;
- CallBackInterface *cb1 = new CallBack(23);
+ /*CallBackInterface *cb1 = new CallBack(23);
CallBackInterface *cb2 = new CallBack(33);
CallBackInterface *cb3 = new CallBack(43);
vector<CallBackInterface*> cb;
cbsec.push_back(cb6);
tcStub->registerCallback(cbsec);
cout << "Return value from callback: " << tcStub->callBack() << endl;
-
+*/
vector<data> dataset;
data testdata;
dataset.push_back(testdata);
dataset.push_back(testdata2);
- tcStub->handleStruct(dataset);
+ vector<data> result = tcStub->handleStruct(dataset);
+ for (data dt : result) {
+ cout << dt.name << " ";
+ cout << dt.value << " ";
+ cout << dt.year << endl;
+ }
- vector<EnumC> vecEn;
+/* vector<EnumC> vecEn;
vecEn.push_back(APPLE);
vecEn.push_back(ORANGE);
vecEn.push_back(APPLE);
delete tcStub;
delete cb1;
delete cb2;
- delete cb3;
+ delete cb3;*/
return 0;
}
void registerCallback(CallBackInterface* _cb);
void registerCallback(vector<CallBackInterface*>_cb);
int callBack();
- void handleStruct(vector<data> vecData);
+ vector<data> handleStruct(vector<data> vecData);
vector<EnumC> handleEnum(vector<EnumC> vecEn);
void ____init_CallBack(); // thread
void ____registerCallBack(); // tell the other side that we are ready
rmiCall = new IoTRMICall(_port, _address, _rev, _bResult);
ports = _ports;
// Start thread
- thread th1 (&TestClass_Stub::____init_CallBack, this);
- th1.detach();
+// thread th1 (&TestClass_Stub::____init_CallBack, this);
+// th1.detach();
//th1.join();
- ____registerCallBack();
+// ____registerCallBack();
}
}
-void TestClass_Stub::handleStruct(vector<data> vecData) {
+vector<data> TestClass_Stub::handleStruct(vector<data> vecData) {
int numParam = 1;
int methodId = 11;
int numParam2 = 3*vecData.size();
int methodId2 = 10;
- string retType2 = "void";
+ string retType2 = "int";
string paramCls2[numParam2];
void* paramObj2[numParam2];
int pos = 0;
paramCls2[pos] = "int";
paramObj2[pos] = &vecData[i].year; pos++;
}
- void* retObj2 = NULL;
+ // RETURN STRUCT OBJECT
+ // Get length of struct array
+ int structsize1 = 0;
+ void* retObj2 = { &structsize1 };
+ // IF we don't have returned struct objects, then it's just "void* retObj2 = NULL;"
rmiCall->remoteCall(objectId, methodId2, retType2, paramCls2, paramObj2, numParam2, retObj2);
+ cout << "Struct length: " << structsize1 << endl;
+
+ // Get the returned objects
+ string retCls[3*structsize1];
+ void* retObj3[3*structsize1];
+ int numRet = 3*structsize1;
+ // define array of everything
+ string param1[structsize1];
+ float param2[structsize1];
+ int param3[structsize1];
+ pos = 0;
+ for(int i=0; i < structsize1; i++) {
+ retCls[pos] = "string";
+ retObj3[pos++] = ¶m1[i];
+ retCls[pos] = "float";
+ retObj3[pos++] = ¶m2[i];
+ retCls[pos] = "int";
+ retObj3[pos++] = ¶m3[i];
+ }
+ rmiCall->getStructObjects(retCls, numRet, retObj3);
+ vector<data> dat(structsize1);
+ pos = 0;
+ for (int i=0; i < structsize1; i++) {
+ dat[i].name = param1[i];
+ dat[i].value = param2[i];
+ dat[i].year = param3[i];
+ }
+
+ return dat;
}
ex.printStackTrace();
throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
}
- System.out.println("Return object bytes: " + Arrays.toString(retObjBytes));
retObj = IoTRMIUtil.getParamObject(retType, retGenTypeVal, retObjBytes);
}
return retObj;
}
+ /**
+ * remoteCall() calls a method remotely by passing in parameters and getting a return Object
+ */
+ public synchronized Object[] getStructObjects(Class<?>[] retType, Class<?>[] retGenTypeVal) {
+
+ // Receive return value and return it to caller
+ Object[] retObj = null;
+ byte[] retObjBytes = null;
+ try {
+ retObjBytes = rmiClient.receiveBytes(retObjBytes);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
+ }
+ retObj = getReturnObjects(retObjBytes, retType, retGenTypeVal);
+
+ return retObj;
+ }
+
+
+ public Object[] getReturnObjects(byte[] retBytes, Class<?>[] arrCls, Class<?>[] arrGenValCls) {
+
+ // Byte scanning position
+ int pos = 0;
+ Object[] retObj = new Object[arrCls.length];
+ for (int i=0; i < arrCls.length; i++) {
+
+ String retType = arrCls[i].getSimpleName();
+ int retSize = rmiUtil.getTypeSize(retType);
+ // Get the 32-bit field in the byte array to get the actual
+ // length (this is a param with indefinite length)
+ if (retSize == -1) {
+ byte[] bytRetLen = new byte[IoTRMIUtil.RETURN_LEN];
+ System.arraycopy(retBytes, pos, bytRetLen, 0, IoTRMIUtil.RETURN_LEN);
+ pos = pos + IoTRMIUtil.RETURN_LEN;
+ retSize = IoTRMIUtil.byteArrayToInt(bytRetLen);
+ }
+ byte[] retObjBytes = new byte[retSize];
+ System.arraycopy(retBytes, pos, retObjBytes, 0, retSize);
+ pos = pos + retSize;
+ retObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenValCls[i], retObjBytes);
+ }
+
+ return retObj;
+ }
+
+
public static void main(String[] args) throws Exception {
String[] test = { "123", "456", "789" };
Boolean[] c2 = (Boolean[]) IoTRMIUtil.getParamObjectArray(Boolean[].class, b2);
System.out.println(Arrays.toString(c2));
+ IoTRMICall rmiCall = new IoTRMICall(1234, "localhost", 0);
+ byte[] retObjBytes = { 0, 0, 4, -46, 0, 0, 0, 10, 116, 101, 115, 116, 115, 116, 114, 105, 110, 103, 0, 0, 21, 56 };
+ //Class<?>[] retCls = new Class<?>[] { int.class, String.class, int.class };
+ Object[] retObj = rmiCall.getReturnObjects(retObjBytes, new Class<?>[] { int.class, String.class, int.class },
+ new Class<?>[] { null, null, null });
+ System.out.println("Ret object 1: " + retObj[0]);
+ System.out.println("Ret object 2: " + retObj[1]);
+ System.out.println("Ret object 3: " + retObj[2]);
+
// List
/*List<Long> list = new ArrayList<Long>();
list.add(12345678l);
byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
rmiServer.sendBytes(retObjBytes);
}
+
+
+ /**
+ * sendReturnObj() overloaded to send multiple return objects for structs
+ */
+ public void sendReturnObj(Class<?>[] retCls, Object[] retObj) throws IOException {
+
+ // Send back return value
+ byte[] retObjBytes = returnToBytes(retCls, retObj);
+ rmiServer.sendBytes(retObjBytes);
+ }
+
+
+ /**
+ * returnToBytes() takes array of objects and generates bytes
+ */
+ public byte[] returnToBytes(Class<?>[] retCls, Object[] retObj) {
+
+ // Get byte arrays and calculate method bytes length
+ int numbRet = retObj.length;
+ int retLen = 0;
+ byte[][] objBytesArr = new byte[numbRet][];
+ for (int i = 0; i < numbRet; i++) {
+ // Get byte arrays for the objects
+ objBytesArr[i] = IoTRMIUtil.getObjectBytes(retObj[i]);
+ String clsName = retCls[i].getSimpleName();
+ int retObjLen = rmiUtil.getTypeSize(clsName);
+ if (retObjLen == -1) { // indefinite length - store the length first
+ retLen = retLen + IoTRMIUtil.RETURN_LEN;
+ }
+ retLen = retLen + objBytesArr[i].length;
+ }
+ // Construct return in byte array
+ byte[] retBytes = new byte[retLen];
+ int pos = 0;
+ // Iteration for copying bytes
+ for (int i = 0; i < numbRet; i++) {
+
+ String clsName = retCls[i].getSimpleName();
+ int retObjLen = rmiUtil.getTypeSize(clsName);
+ if (retObjLen == -1) { // indefinite length
+ retObjLen = objBytesArr[i].length;
+ byte[] retLenBytes = IoTRMIUtil.intToByteArray(retObjLen);
+ System.arraycopy(retLenBytes, 0, retBytes, pos, IoTRMIUtil.RETURN_LEN);
+ pos = pos + IoTRMIUtil.RETURN_LEN;
+ }
+ System.arraycopy(objBytesArr[i], 0, retBytes, pos, retObjLen);
+ pos = pos + retObjLen;
+ }
+
+ return retBytes;
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ int port = 5010;
+ IoTRMIObject rmiObj = new IoTRMIObject(port);
+
+ Class<?>[] retCls = new Class<?>[] { int.class, String.class, int.class };
+ Object[] retObj = new Object[] { 1234, "teststring", 5432 };
+
+ System.out.println("Bytes: " + Arrays.toString(rmiObj.returnToBytes(retCls, retObj)));
+ }
}
public final static int OBJECT_ID_LEN = 4; // 4 bytes = 32 bits
public final static int METHOD_ID_LEN = 4; // 4 bytes = 32 bits
public final static int PARAM_LEN = 4; // 4 bytes = 32 bits (4-byte field that stores the length of the param)
+ public final static int RETURN_LEN = 4; // 4 bytes = 32 bits (4-byte field that stores the length of the return object)
public final static int SHT_LEN = 2;
public final static int INT_LEN = 4;
return sum;
}
- public void handleStruct(StructJ[] data) {
+ public StructJ[] handleStruct(StructJ[] data) {
for (StructJ str : data) {
System.out.println("Name: " + str.name);
System.out.println("Value: " + str.value);
System.out.println("Year: " + str.year);
}
+
+ StructJ test = new StructJ();
+ test.name = "Anonymous";
+ test.value = 1.33f;
+ test.year = 2016;
+
+ data[0] = test;
+
+ return data;
}
public void registerCallback(CallBackInterface _cb);
public void registerCallback(CallBackInterface[] _cb);
public int callBack();
- public void handleStruct(StructJ[] data);
+ public StructJ[] handleStruct(StructJ[] data);
public EnumJ[] handleEnum(EnumJ[] en);
}
}
- public void handleStruct(StructJ[] data) {
+ public StructJ[] handleStruct(StructJ[] data) {
- tc.handleStruct(data);
+ return tc.handleStruct(data);
}
}
- public void ___handleStruct(int structsize1) {
+ public void ___handleStruct(int structsize1) throws IOException {
Class<?>[] paramCls = new Class<?>[3*structsize1];
Class<?>[] paramClsVal = new Class<?>[3*structsize1];
data[i].value = (float) paramObj[pos++];
data[i].year = (int) paramObj[pos++];
}
- tc.handleStruct(data);
+ // Just the following if there is no returned value
+ //tc.handleStruct(data);
+ StructJ[] retStruct = tc.handleStruct(data);
+ // Return length first
+ int structsize2 = retStruct.length;
+ Object retObj = structsize2;
+ rmiObj.sendReturnObj(retObj);
+ // Send the actual struct members
+ // Calculate the size of the array
+ Class<?>[] retCls = new Class<?>[3*structsize2];
+ Object[] retObj2 = new Object[3*structsize2];
+ // Handle with for loop
+ pos = 0;
+ for(int i = 0; i < structsize2; i++) {
+ retCls[pos] = String.class;
+ retObj2[pos++] = data[i].name;
+ retCls[pos] = float.class;
+ retObj2[pos++] = data[i].value;
+ retCls[pos] = int.class;
+ retObj2[pos++] = data[i].year;
+ }
+ rmiObj.sendReturnObj(retCls, retObj2);
}
TestClass tc = new TestClass(3, 5f, "7911");
TestClass_Skeleton tcSkel = new TestClass_Skeleton(tc, port);
-/* String[] methodSignatures = TestClass_CBSkeleton.getMethodSignatures();
- IoTRMIObject rmiObj = new IoTRMIObject(port, methodSignatures);
- Map<Integer,TestClassInterface> mapCBObject = new HashMap<Integer,TestClassInterface>();
-
- // Can replace for-loop with while-loop if necessary
- for (int i = 1; i < 3; i++) {
- TestClassInterface tcSkel = new TestClass_CBSkeleton(tc, i);
- mapCBObject.put(i, tcSkel);
- }
-
- Object retObj = null;
- while (true) {
- byte[] method = rmiObj.getMethodBytes();
- int objId = IoTRMIObject.getObjectId(method);
- TestClass_CBSkeleton tcSkel = (TestClass_CBSkeleton) mapCBObject.get(objId);
- if (tcSkel != null) {
- rmiObj.setMethodBytes(method);
- retObj = tcSkel.invokeMethod(rmiObj);
- }
- if (retObj != null) {
- rmiObj.sendReturnObj(retObj);
- }
- }
-*/
- //int objectId = 1;
- //System.out.println("Creating 0 object");
- //TestClass_Skeleton tcSkel1 = new TestClass_Skeleton(tc, rmiObj, objectId);
- //System.out.println("Creating 1 object");
- //objectId = 2;
- //TestClass_Skeleton tcSkel2 = new TestClass_Skeleton(tc, rmiObj, objectId);
- //System.out.println("Creating 2 object");
-
- /*for (int i = 1; i < 3; i++) {
- final int objectId = i;
- Thread thread = new Thread() {
- public void run() {
- try{
- TestClass_Skeleton tcSkel = new TestClass_Skeleton(tc, rmiObj, objectId);
- } catch (Exception ex){
- ex.printStackTrace();
- throw new Error("Error instantiating class CallBack_Skeleton!");
- }
- }
- };
- thread.start();
- }*/
}
}
address = _address;
ports = _ports;
- //rmiCall = new IoTRMICall(_port, _address, _rev, methodSignatures);
rmiCall = new IoTRMICall(_port, _address, _rev);
listCBObj = new ArrayList<CallBackInterface>();
___initCallBack();
Thread thread = new Thread() {
public void run() {
try{
- //String[] methodSignatures = CallBack_CBSkeleton.getMethodSignatures();
- //rmiObj = new IoTRMIObject(ports[0], methodSignatures);
+ System.out.println("Created server with port: " + ports[0]);
rmiObj = new IoTRMIObject(ports[0]);
Object retObj = null;
while (true) {
// port, address, rev
Class<?>[] paramCls = new Class<?>[] { int.class, String.class, int.class };
Object[] paramObj = new Object[] { ports[0], address, 0 };
- //rmiCall.remoteCall(objectId, sign, retType, null, null, paramCls, paramObj);
rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
}
}
- public void handleStruct(StructJ[] data) {
+ public StructJ[] handleStruct(StructJ[] data) {
int methodId = 11;
Class<?> retType = void.class;
rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
int methodId2 = 10;
- Class<?> retType2 = void.class;
+ Class<?> retType2 = int.class; // return type is integer if it is a struct!!!
// Calculate the size of the array
Class<?>[] paramCls2 = new Class<?>[3*data.length];
Object[] paramObj2 = new Object[3*data.length];
paramObj2[pos++] = data[i].year;
}
System.out.println(Arrays.toString(paramObj2));
- rmiCall.remoteCall(objectId, methodId2, retType2, null, paramCls2, paramObj2);
+ Object retObj = rmiCall.remoteCall(objectId, methodId2, retType2, null, paramCls2, paramObj2);
+ // RETURN STRUCT
+ // Get the length of the struct first
+ int structsize1 = (int) retObj;
+ // Construct the struct
+ Class<?>[] retCls = new Class<?>[3*structsize1];
+ Class<?>[] retClsVal = new Class<?>[3*structsize1];
+ pos = 0;
+ for(int i=0; i < structsize1; i++) {
+ retCls[pos] = String.class;
+ retClsVal[pos++] = null;
+ retCls[pos] = float.class;
+ retClsVal[pos++] = null;
+ retCls[pos] = int.class;
+ retClsVal[pos++] = null;
+ }
+ Object[] retObj2 = rmiCall.getStructObjects(retCls,
+ retClsVal);
+ StructJ[] dataRet = new StructJ[structsize1];
+ for (int i=0; i < structsize1; i++) {
+ dataRet[i] = new StructJ();
+ }
+ pos = 0;
+ for(int i=0; i < structsize1; i++) {
+ dataRet[i].name = (String) retObj2[pos++];
+ dataRet[i].value = (float) retObj2[pos++];
+ dataRet[i].year = (int) retObj2[pos++];
+ }
+
+ return dataRet;
}
CallBackInterface cb6 = new CallBack(12);
CallBackInterface[] cbt = { cb4, cb5, cb6 };
tcstub.registerCallback(cbt);
- System.out.println("Return value from callback: " + tcstub.callBack());
+ System.out.println("Return value from callback: " + tcstub.callBack());*/
StructJ[] data = new StructJ[2];
for (int i=0; i<2; i++) {
System.out.println("Value: " + str.value);
System.out.println("Year: " + str.year);
}
- tcstub.handleStruct(data);*/
+ StructJ[] strj = tcstub.handleStruct(data);
+ for (StructJ str : strj) {
+ System.out.println("Name: " + str.name);
+ System.out.println("Value: " + str.value);
+ System.out.println("Year: " + str.year);
+ }
+
EnumJ[] en = { EnumJ.APPLE, EnumJ.ORANGE, EnumJ.APPLE, EnumJ.GRAPE };
EnumJ[] res = tcstub.handleEnum(en);