Adding premature C++ side; supporting only primitive types (including string) for now
authorrtrimana <rtrimana@uci.edu>
Mon, 24 Oct 2016 23:18:35 +0000 (16:18 -0700)
committerrtrimana <rtrimana@uci.edu>
Mon, 24 Oct 2016 23:18:35 +0000 (16:18 -0700)
14 files changed:
common.mk
iotjava/Makefile
iotjava/iotrmi/C++/IoTRMICall.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/IoTRMIObject.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/IoTRMITypes.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/IoTRMIUtil.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/IoTSocket.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/IoTSocketClient.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/IoTSocketServer.hpp [new file with mode: 0644]
iotjava/iotrmi/C++/TestClass.hpp [new file with mode: 0644]
iotjava/iotrmi/Java/IoTRMICall.java
iotjava/iotrmi/Java/IoTRMIObject.java
iotjava/iotrmi/Java/IoTRMIUtil.java
iotjava/iotrmi/Java/sample/TestClass.java

index ed6efc9426440bb8e302e888d199e7307623f3bb..0b14291e674bf31caf41decf418aecc1625d3223 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -1,3 +1,4 @@
+G++ := g++
 JAVA := java
 JAR := jar
 JAVADOC := javadoc
 JAVA := java
 JAR := jar
 JAVADOC := javadoc
index d9b968f16878175ce1d431944498e61e021f42ab..985e41e67c6073bcf3745a6b5243bc0dd10b9c37 100644 (file)
@@ -30,9 +30,15 @@ runtime:
 # RMI compilation and run
 PHONY += rmi
 rmi:
 # RMI compilation and run
 PHONY += rmi
 rmi:
+       mkdir -p $(BIN_DIR)
        $(JAVAC) -cp . -d $(BIN_DIR) iotrmi/*.java
        $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java
        $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/sample/*.java
        $(JAVAC) -cp . -d $(BIN_DIR) iotrmi/*.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++/IoTRMICall.cpp -o $(BIN_DIR)/iotrmi/C++/IoTRMICall.out --std=c++11
+       $(G++) iotrmi/C++/IoTRMIObject.cpp -o $(BIN_DIR)/iotrmi/C++/IoTRMIObject.out --std=c++11
 
 PHONY += run-rmiserver
 run-rmiserver:
 
 PHONY += run-rmiserver
 run-rmiserver:
diff --git a/iotjava/iotrmi/C++/IoTRMICall.hpp b/iotjava/iotrmi/C++/IoTRMICall.hpp
new file mode 100644 (file)
index 0000000..8503cdf
--- /dev/null
@@ -0,0 +1,162 @@
+/** Class IoTRMICall provides methods that the upper
+ *  layers can use to transport and invoke methods
+ *  when using IoTSocket, IoTSocketClient and IoTSocketServer.
+ *  <p>
+ *  This class serves in the stub part of the RMI
+ *  communication. It bridges and creates RMI requests to be
+ *  transferred into the RMI object.
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-10-18
+ */
+#ifndef _IOTRMICALL_HPP__
+#define _IOTRMICALL_HPP__
+
+#include <iostream>
+#include <string>
+#include "IoTRMIUtil.hpp"
+#include "IoTSocketClient.hpp"
+
+using namespace std;
+
+class IoTRMICall {
+       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* method, int numParam);
+               void*   remoteCall(string methodSign, string retType, string paramCls[], 
+                                                               void* paramObj[], int numParam, void* retObj);
+
+       private:
+               IoTRMIUtil              *rmiUtil;
+               IoTSocketClient *rmiClient;
+};
+
+
+// Constructor
+IoTRMICall::IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult) {
+
+       rmiUtil = new IoTRMIUtil();
+       if (rmiUtil == NULL) {
+               perror("IoTRMICall: IoTRMIUtil isn't initialized!");
+       }
+       rmiClient = new IoTSocketClient(_port, _address, _rev, _bResult);
+       if (rmiClient == NULL) {
+               perror("IoTRMICall: IoTSocketClient isn't initialized!");
+       }
+}
+
+
+// Destructor
+IoTRMICall::~IoTRMICall() {
+
+       // Clean up
+       if (rmiUtil != NULL) {
+               
+               delete rmiUtil;
+               rmiUtil = NULL;         
+       }
+       if (rmiClient != NULL) {
+
+               fflush(NULL);
+               rmiClient->close();             
+               delete rmiClient;
+               rmiClient = NULL;               
+       }
+}
+
+
+// Calls a method remotely by passing in parameters and getting a return object
+void* IoTRMICall::remoteCall(string methodSign, string retType, string paramCls[], 
+                                                               void* paramObj[], int numParam, void* retObj) {
+
+       // Send input parameters
+       int len = methodLength(paramCls, paramObj, numParam);
+       char method[len];
+       methodToBytes(methodSign, paramCls, paramObj, method, numParam);
+       // Send bytes
+       fflush(NULL);
+       rmiClient->sendBytes(method, len);
+       fflush(NULL);
+       // Receive return value and return it to caller
+       if (retType.compare("void") == 0)
+               // Just make it NULL if it's a void return
+               retObj = NULL;
+       else {
+               int retLen = 0;
+               char* retObjBytes = NULL;
+               retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
+               retObj = IoTRMIUtil::getParamObject(retObj, retType.c_str(), 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;
+       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();
+                       }
+                       // 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[], 
+               void* paramObj[], char* method, int numParam) {
+
+       // 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;
+       // 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();
+                       }
+                       // Write the parameter length
+                       char prmLenBytes[IoTRMIUtil::METHOD_ID_LEN];
+                       IoTRMIUtil::intToByteArray(paramLen, prmLenBytes);
+                       memcpy(method + pos, prmLenBytes, IoTRMIUtil::PARAM_LEN);                       
+                       pos = pos + IoTRMIUtil::PARAM_LEN;
+               }
+               // Get array of bytes and put it in the array of array of bytes
+               char objBytes[paramLen];
+               IoTRMIUtil::getObjectBytes(objBytes, paramObj[i], paramCls[i].c_str());
+               memcpy(method + pos, objBytes, paramLen);
+               pos = pos + paramLen;
+       }
+
+       return method;
+}
+
+
+#endif
+
+
diff --git a/iotjava/iotrmi/C++/IoTRMIObject.hpp b/iotjava/iotrmi/C++/IoTRMIObject.hpp
new file mode 100644 (file)
index 0000000..a6e4cb1
--- /dev/null
@@ -0,0 +1,179 @@
+/** Class IoTRMIObject provides methods that the upper
+ *  layers can use to transport and invoke methods
+ *  when using IoTSocket, IoTSocketClient and IoTSocketServer.
+ *  <p>
+ *  This class serves in the skeleton part of the RMI
+ *  communication. It instatiate an RMI object and activate
+ *  a server process that handles RMI requests.
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-10-24
+ */
+#ifndef _IOTRMIOBJECT_HPP__
+#define _IOTRMIOBJECT_HPP__
+
+#include <iostream>
+#include <string>
+#include "IoTRMIUtil.hpp"
+#include "IoTSocketServer.hpp"
+
+using namespace std;
+
+class IoTRMIObject {
+       public:
+               IoTRMIObject(int _port, bool* _bResult, string _methodSign[], int _size);
+               ~IoTRMIObject();
+               // Public methods
+               void            sendReturnObj(void* retObj, string type);
+               void            getMethodBytes();
+               string          getSignature();
+               void**          getMethodParams(string paramCls[], int numParam, void* paramObj[]);
+
+       private:
+               map<int,string>         mapHash2Sign;
+               IoTRMIUtil                      *rmiUtil;
+               IoTSocketServer         *rmiServer;
+               char*                           methodBytes;
+               int                                     methodLen;
+
+               // Private methods
+               void                            getMethodIds(string methodSign[], int size);
+};
+
+
+// Constructor
+IoTRMIObject::IoTRMIObject(int _port, bool* _bResult, string _methodSign[], int _size) {
+
+       rmiUtil = new IoTRMIUtil();
+       if (rmiUtil == NULL) {
+               perror("IoTRMIObject: IoTRMIUtil isn't initialized!");
+       }
+
+       methodBytes = NULL;
+       methodLen = 0;
+       getMethodIds(_methodSign, _size);
+
+       rmiServer = new IoTSocketServer(_port, _bResult);
+       if (rmiServer == NULL) {
+               perror("IoTRMIObject: IoTSocketServer isn't initialized!");
+       }
+       fflush(NULL);
+       rmiServer->connect();
+       fflush(NULL);
+}
+
+
+// Destructor
+IoTRMIObject::~IoTRMIObject() {
+
+       // Clean up
+       if (rmiUtil != NULL) {
+               
+               delete rmiUtil;
+               rmiUtil = NULL;         
+       }
+       if (rmiServer != NULL) {
+
+               fflush(NULL);
+               rmiServer->close();     
+               delete rmiServer;
+               rmiServer = NULL;               
+       }
+}
+
+
+// Send return values in bytes to the caller
+void IoTRMIObject::sendReturnObj(void* retObj, string type) {
+
+       // Find the length of return object in bytes
+       int retLen = rmiUtil->getTypeSize(type);
+       if (retLen == -1) {
+               if (type.compare("string") == 0) {
+                       // Get the length of the string through void* casting to string*
+                       retLen = (*(string*)retObj).length();
+               }
+       }
+       // Need object bytes variable
+       char retObjBytes[retLen];
+       IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
+       rmiServer->sendBytes(retObjBytes, retLen);
+}
+
+
+// Get method bytes from the socket
+void IoTRMIObject::getMethodBytes() {
+
+       // Get method in bytes and update method length
+       methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
+       fflush(NULL);
+       IoTRMIUtil::printBytes(methodBytes, methodLen, false);
+}
+
+
+// Get signature from the method-Id-to-method-signature map
+string IoTRMIObject::getSignature() {
+
+       // Get method Id
+       char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
+       memcpy(methodIdBytes, methodBytes, IoTRMIUtil::METHOD_ID_LEN);
+       // Get method object 
+       int methodId = 0;
+       IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
+       cout << "Method Id: " << methodId << endl;
+       
+       return mapHash2Sign.find(methodId)->second;
+}
+
+
+// Get method parameters and return an array of parameter objects
+//
+// For primitive objects:
+// | 32-bit method ID | m-bit actual data (fixed length)  |
+// 
+// For string, arrays, and non-primitive objects:
+// | 32-bit method ID | 32-bit length | n-bit actual data | ...
+void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
+
+       // Byte scanning position
+       int pos = IoTRMIUtil::METHOD_ID_LEN;
+       for (int i = 0; i < numParam; i++) {
+
+               int paramLen = rmiUtil->getTypeSize(paramCls[i]);
+               // Get the 32-bit field in the byte array to get the actual
+               //              length (this is a param with indefinite length)
+               if (paramLen == -1) {
+                       char bytPrmLen[IoTRMIUtil::PARAM_LEN];
+                       memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
+                       pos = pos + IoTRMIUtil::PARAM_LEN;
+                       int* prmLenPtr = IoTRMIUtil::byteArrayToInt(&paramLen, bytPrmLen);
+                       paramLen = *prmLenPtr;
+               }
+               char paramBytes[paramLen];
+               memcpy(paramBytes, methodBytes + pos, paramLen);
+               pos = pos + paramLen;
+               paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes);
+
+       }
+       // Delete methodBytes
+       delete[] methodBytes;
+
+       return paramObj;
+}
+
+
+// *************
+//    Helpers
+// *************
+void IoTRMIObject::getMethodIds(string methodSign[], int size) {
+
+       for(int i = 0; i < size; i++) {
+               int methodId = IoTRMIUtil::hashCode(methodSign[i]);
+               mapHash2Sign[methodId] = methodSign[i];
+       }
+}
+
+
+#endif
+
+
diff --git a/iotjava/iotrmi/C++/IoTRMITypes.hpp b/iotjava/iotrmi/C++/IoTRMITypes.hpp
new file mode 100644 (file)
index 0000000..2c32f47
--- /dev/null
@@ -0,0 +1,193 @@
+/** Class IoTRMITypes is a class that provides type translations.
+ *  <p>
+ *  It stores C++ and Java types.
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-10-18
+ */
+#ifndef _IOTRMITYPES_HPP__
+#define _IOTRMITYPES_HPP__
+
+#include <iostream>
+#include <string>
+#include <map>
+#include <vector>
+
+using namespace std;
+
+class IoTRMITypes {
+
+       public:
+               /* Public constants */
+               const static int NUM_PRIMITIVES = 19;
+               const static int NUM_NONPRIMITIVES = 6;
+
+               /**
+                * Primitive data types in Java
+                */
+               const static string primitivesJava[NUM_PRIMITIVES];
+
+
+               /**
+                * Primitive data types in C++ to map the primitives list
+                */
+               const static string primitivesCplus[NUM_PRIMITIVES];
+
+
+               /**
+                * Primitive sizes in Java - Long is 8 bytes and char is 2 bytes
+                */
+               const static int primitivesJavaSizes[NUM_PRIMITIVES];
+
+
+               /**
+                * Primitive sizes in Cplus - Long is 4 bytes and char is 1 byte
+                */
+               const static int primitivesCplusSizes[NUM_PRIMITIVES];
+
+
+               /**
+                * Non-primitive Java data types
+                */
+               const static string nonPrimitivesJava[NUM_NONPRIMITIVES];
+
+
+               /**
+                * Non-primitive C++ data types
+                */
+               const static string nonPrimitivesCplus[NUM_NONPRIMITIVES];
+
+
+               /* Methods */
+               static void             arraysToMap(map<string,string> &srcMap, const vector<string> arrKey, 
+                       const vector<string> arrVal);
+               static void             arraysToMap(map<string,int> &srcMap, const vector<string> arrKey, 
+                       const vector<int> arrVal);
+               static void     arraysToMap(map<void*,void*> &srcMap, const vector<void*> arrKey, 
+                       const vector<void*> arrVal);
+};
+
+
+const string IoTRMITypes::primitivesJava[IoTRMITypes::NUM_PRIMITIVES] = {
+
+       "byte",                 // 1 byte
+       "Byte",                 // 1 byte
+       "short",                // 2 bytes
+       "Short",                // 2 bytes
+       "int",                  // 4 bytes
+       "Integer",              // 4 bytes
+       "long",                 // 8 bytes
+       "Long",                 // 8 bytes
+       "float",                // 4 bytes
+       "Float",                // 4 bytes
+       "double",               // 8 bytes
+       "Double",               // 8 bytes
+       "boolean",              // 1 bytes
+       "Boolean",              // 1 bytes
+       "char",                 // 2 bytes
+       "Character",    // 2 bytes
+       "string",               // indefinite
+       "String",               // indefinite
+       "void"                  // 0 byte
+};
+
+
+const string IoTRMITypes::primitivesCplus[IoTRMITypes::NUM_PRIMITIVES] = {
+
+       "char",                 // 1 byte
+       "char",                 // 1 byte
+       "short",                // 2 bytes
+       "short",                // 2 bytes
+       "int",                  // 4 bytes
+       "int",                  // 4 bytes
+       "int64_t",              // 8 bytes
+       "int64_t",              // 8 bytes
+       "float",                // 4 bytes
+       "float",                // 4 bytes
+       "double",               // 8 bytes
+       "double",               // 8 bytes
+       "bool",                 // 1 byte
+       "bool",                 // 1 byte
+       "char",                 // 2 byte
+       "char",                 // 2 byte
+       "string",               // indefinite
+       "string",               // indefinite
+       "void"                  // 0 byte
+};
+
+
+const int IoTRMITypes::primitivesJavaSizes[IoTRMITypes::NUM_PRIMITIVES] = {
+
+       1, 1, 2, 2, 4, 4, 8, 8, 4, 4, 8, 8, 1, 1, 2, 2, -1, -1, 0
+};
+
+
+const int IoTRMITypes::primitivesCplusSizes[IoTRMITypes::NUM_PRIMITIVES] = {
+
+       1, 1, 2, 2, 4, 4, 8, 8, 4, 4, 8, 8, 1, 1, 2, 2, -1, -1, 0
+};
+
+
+const string IoTRMITypes::nonPrimitivesJava[IoTRMITypes::NUM_NONPRIMITIVES] = {
+
+       "Set",
+       "HashSet",
+       "Map",
+       "HashMap",
+       "List",
+       "ArrayList"
+};
+
+
+const string IoTRMITypes::nonPrimitivesCplus[IoTRMITypes::NUM_NONPRIMITIVES] = {
+
+       "set",
+       "unordered_set",
+       "map",
+       "unordered_map",
+       "list",
+       "list"
+};
+
+
+/**================
+ * Helper functions
+ **================
+ */
+// Inserting array members into a Map object
+// that maps arrKey to arrVal objects
+void IoTRMITypes::arraysToMap(map<string,string> &srcMap, const vector<string> arrKey, 
+       const vector<string> arrVal) {
+
+       for(int i = 0; i < arrKey.size(); i++) {
+
+               srcMap[arrKey[i]] = arrVal[i];
+       }
+}
+
+
+// Inserting array members into a Map object
+// that maps arrKey to arrVal objects
+void IoTRMITypes::arraysToMap(map<string,int> &srcMap, const vector<string> arrKey, 
+       const vector<int> arrVal) {
+
+       for(int i = 0; i < arrKey.size(); i++) {
+
+               srcMap[arrKey[i]] = arrVal[i];
+       }
+}
+
+
+// Inserting array members into a Map object
+// that maps arrKey to arrVal objects
+void IoTRMITypes::arraysToMap(map<void*,void*> &srcMap, const vector<void*> arrKey, 
+       const vector<void*> arrVal) {
+
+       for(int i = 0; i < arrKey.size(); i++) {
+
+               srcMap[arrKey[i]] = arrVal[i];
+       }
+}
+
+#endif
diff --git a/iotjava/iotrmi/C++/IoTRMIUtil.hpp b/iotjava/iotrmi/C++/IoTRMIUtil.hpp
new file mode 100644 (file)
index 0000000..677612b
--- /dev/null
@@ -0,0 +1,389 @@
+/** Class IoTRMIUtil provides methods that the upper
+ *  layers can use to transport and invoke methods
+ *  when using IoTSocket, IoTSocketClient and IoTSocketServer.
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-10-18
+ */
+#ifndef _IOTRMIUTIL_HPP__
+#define _IOTRMIUTIL_HPP__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <endian.h>
+#include <cxxabi.h>
+#include <cstdlib>
+#include <memory>
+#include <typeinfo>
+
+#include <iostream>
+#include <string>
+#include <string.h>
+
+#include "IoTRMITypes.hpp"
+
+using namespace std;
+
+class IoTRMIUtil {
+
+       public:
+               IoTRMIUtil();
+               //~IoTRMIUtil();
+               
+               // Helper functions
+               static void             printBytes(char* bytes, const int len, const bool hex);
+               static int              hashCode(string str);
+               static char*    getHashCodeBytes(string methodSign, char* bytes);
+               int                     getTypeSize(string type);
+               
+               // Primitives to byte array
+               static char*    shortToByteArray(short i, char* bytes);
+               static char*    intToByteArray(int i, char* bytes);
+               static char*    longToByteArray(int64_t i, char* bytes);
+               static char*    floatToByteArray(float f, char* bytes);
+               static char*    doubleToByteArray(double d, char* bytes);
+               static char*    charToByteArray(char c, char* bytes);
+               static char*    booleanToByteArray(bool c, char* bytes);
+               static char*    stringToByteArray(string c, char* bytes);
+
+               // Byte array to primitives
+               static short*   byteArrayToShort(short* result, char* bytes);
+               static int*     byteArrayToInt(int* result, char* bytes);
+               static int64_t* byteArrayToLong(int64_t* result, char* bytes);
+               static float*   byteArrayToFloat(float* result, char* bytes);
+               static double*  byteArrayToDouble(double* result, char* bytes);
+               static char*    byteArrayToChar(char* result, char* bytes);
+               static bool*    byteArrayToBoolean(bool* result, char* bytes);
+               static string*  byteArrayToString(string* result, char* bytes);
+
+               // Get parameter object from byte array
+               static void*    getParamObject(void* retObj, const char* type, char* paramBytes);
+               static char*    getObjectBytes(char* retObjBytes, void* obj, const char* type);
+
+               // Constants
+               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)
+               
+       private:
+               map<string,string>      mapPrimitives;
+               map<string,int>         mapPrimitiveSizesJava;
+               map<string,int>         mapPrimitiveSizesCplus;
+               map<string,string>      mapNonPrimitives;
+};
+
+
+// Constructor
+IoTRMIUtil::IoTRMIUtil() {
+
+       // Prepare vectors for inputs
+       std::vector<string> primJava (IoTRMITypes::primitivesJava, 
+               IoTRMITypes::primitivesJava + sizeof(IoTRMITypes::primitivesJava)/sizeof(string));
+       std::vector<string> primCplus (IoTRMITypes::primitivesCplus, 
+               IoTRMITypes::primitivesCplus + sizeof(IoTRMITypes::primitivesCplus)/sizeof(string));
+       std::vector<int> primJavaSizes (IoTRMITypes::primitivesJavaSizes, 
+               IoTRMITypes::primitivesJavaSizes + sizeof(IoTRMITypes::primitivesJavaSizes)/sizeof(int));
+       std::vector<int> primCplusSizes (IoTRMITypes::primitivesCplusSizes, 
+               IoTRMITypes::primitivesCplusSizes + sizeof(IoTRMITypes::primitivesCplusSizes)/sizeof(int));
+       std::vector<string> nonPrimJava (IoTRMITypes::nonPrimitivesJava, 
+               IoTRMITypes::nonPrimitivesJava + sizeof(IoTRMITypes::nonPrimitivesJava)/sizeof(string));
+       std::vector<string> nonPrimCplus (IoTRMITypes::nonPrimitivesCplus, 
+               IoTRMITypes::nonPrimitivesCplus + sizeof(IoTRMITypes::nonPrimitivesCplus)/sizeof(string));
+
+
+       // Write into maps
+       IoTRMITypes::arraysToMap(mapPrimitives, primJava, primCplus);
+       IoTRMITypes::arraysToMap(mapPrimitiveSizesJava, primJava, primJavaSizes); 
+       IoTRMITypes::arraysToMap(mapPrimitiveSizesCplus, primJava, primCplusSizes); 
+       IoTRMITypes::arraysToMap(mapNonPrimitives, nonPrimJava, nonPrimCplus);
+}
+
+// *************
+//    Helpers
+// *************
+void IoTRMIUtil::printBytes(char* bytes, const int len, const bool hex) {
+
+       printf("[ ");
+       for (int i = 0; i < len; i++) {
+               if (hex)        // print in hexadecimal
+                       printf("%x", bytes[i]);
+               else
+                       printf("%d", bytes[i]);
+               if (i < len - 1)
+                       printf(", ");
+       }
+       printf(" ]\n");
+}
+
+
+// Return hashCode value 
+// This mimics the method Object.hashCode() in Java
+int IoTRMIUtil::hashCode(string str)  
+{
+       int hash = 0;
+       int len = str.length();
+       char c;
+       if (len == 0) 
+               return hash;
+       
+       for (int i = 0; i < len; i++) {
+               c = str.at(i);
+               hash = (31*hash) + (int) c;
+       }
+
+       return hash;
+}
+
+
+char* IoTRMIUtil::getHashCodeBytes(string methodSign, char* bytes) {
+
+       int hash = hashCode(methodSign);
+       return intToByteArray(hash, bytes);
+}
+
+
+int IoTRMIUtil::getTypeSize(string type) {
+
+       // Handle the types and find the sizes
+       if (mapPrimitiveSizesCplus.find(type) != mapPrimitiveSizesCplus.end())
+               return mapPrimitiveSizesCplus.find(type)->second;
+       else
+               return -1; // Size is unknown
+}
+
+
+// Getting parameter object based on received byte array
+void* IoTRMIUtil::getParamObject(void* retObj, const char* type, char* paramBytes) {
+
+       if (strcmp(type, "b") == 0 ||
+               strcmp(type, "byte") == 0) {
+               retObj = (void*) &paramBytes[0];
+       } else if ( strcmp(type, "s") == 0 ||
+                               strcmp(type, "short") == 0) {
+               retObj = (void*) byteArrayToShort((short*) retObj, paramBytes);
+       } else if ( strcmp(type, "i") == 0 ||
+                               strcmp(type, "int") == 0) {
+               retObj = (void*) byteArrayToInt((int*) retObj, paramBytes);
+       } else if ( strcmp(type, "l") == 0 ||
+                               strcmp(type, "long") == 0) {
+               retObj = (void*) byteArrayToLong((int64_t*) retObj, paramBytes);
+       } else if ( strcmp(type, "f") == 0 ||
+                               strcmp(type, "float") == 0) {
+               retObj = (void*) byteArrayToFloat((float*) retObj, paramBytes);
+       } else if ( strcmp(type, "d") == 0 ||
+                               strcmp(type, "double") == 0) {
+               retObj = (void*) byteArrayToDouble((double*) retObj, paramBytes);
+       } else if ( strcmp(type, "b") == 0 ||
+                               strcmp(type, "bool") == 0) {
+               retObj = (void*) byteArrayToBoolean((bool*) retObj, paramBytes);
+       } else if ( strcmp(type, "c") == 0 ||
+                               strcmp(type, "char") == 0) {
+               retObj = (void*) byteArrayToChar((char*) retObj, paramBytes);
+       } else if ( strcmp(type, "Ss") == 0 ||
+                               strcmp(type, "string") == 0) {
+               retObj = (void*) byteArrayToString((string*) retObj, paramBytes);
+       } else {
+               string error = "IoTRMIUtil: Unrecognizable type: " + string(type);
+               throw error;
+       }
+
+       return retObj;
+}
+
+
+// Getting byte array based on parameter and its type
+char* IoTRMIUtil::getObjectBytes(char* retObjBytes, void* obj, const char* type) {
+
+       if (strcmp(type, "b") == 0 ||
+               strcmp(type, "byte") == 0) {
+               retObjBytes = (char*) obj;
+       } else if ( strcmp(type, "s") == 0 ||
+                               strcmp(type, "short") == 0) {
+               retObjBytes = shortToByteArray(*((short*) obj), retObjBytes);
+       } else if ( strcmp(type, "i") == 0 ||
+                               strcmp(type, "int") == 0) {
+               retObjBytes = intToByteArray(*((int*) obj), retObjBytes);
+       } else if ( strcmp(type, "l") == 0 ||
+                               strcmp(type, "long") == 0) {
+               retObjBytes = longToByteArray(*((int64_t*) obj), retObjBytes);
+       } else if ( strcmp(type, "f") == 0 ||
+                               strcmp(type, "float") == 0) {
+               retObjBytes = floatToByteArray(*((float*) obj), retObjBytes);
+       } else if ( strcmp(type, "d") == 0 ||
+                               strcmp(type, "double") == 0) {
+               retObjBytes = doubleToByteArray(*((double*) obj), retObjBytes);
+       } else if ( strcmp(type, "b") == 0 ||
+                               strcmp(type, "bool") == 0) {
+               retObjBytes = booleanToByteArray(*((bool*) obj), retObjBytes);
+       } else if ( strcmp(type, "c") == 0 ||
+                               strcmp(type, "char") == 0) {
+               retObjBytes = charToByteArray(*((char*) obj), retObjBytes);
+       } else if ( strcmp(type, "Ss") == 0 ||
+                               strcmp(type, "string") == 0) {
+               retObjBytes = stringToByteArray(*((string*) obj), retObjBytes);
+       } else {
+               string error = "IoTRMIUtil: Unrecognizable type: " + string(type);
+               throw error;
+       }
+
+       return retObjBytes;
+}
+
+
+// Conversions
+// Primitives to byte array
+char* IoTRMIUtil::shortToByteArray(short s, char* bytes) {
+
+       short sInvert = htobe16(s);
+       //short sInvert = htons(s);
+       memcpy(bytes, &sInvert, sizeof(short));
+
+       return bytes;
+}
+
+
+char* IoTRMIUtil::intToByteArray(int i, char* bytes) {
+
+       int iInvert = htobe32(i);
+       //int iInvert = htonl(i);
+       memcpy(bytes, &iInvert, sizeof(int));
+
+       return bytes;
+}
+
+
+char* IoTRMIUtil::longToByteArray(int64_t l, char* bytes) {
+
+       int64_t lInvert = htobe64(l);
+       memcpy(bytes, &lInvert, sizeof(int64_t));
+
+       return bytes;
+}
+
+
+char* IoTRMIUtil::floatToByteArray(float f, char* bytes) {
+
+       // Copy to int to allow the usage of htobeXX() functions
+       int i = 0;
+       memcpy(&i, &f, sizeof(float));
+       int iInvert = htobe32(i);
+       memcpy(bytes, &iInvert, sizeof(int));
+       
+       return bytes;
+}
+
+
+char* IoTRMIUtil::doubleToByteArray(double d, char* bytes) {
+
+       // Copy to int to allow the usage of htobeXX() functions
+       int64_t i = 0;
+       memcpy(&i, &d, sizeof(double));
+       int64_t iInvert = htobe64(i);
+       memcpy(bytes, &iInvert, sizeof(int64_t));
+       
+       return bytes;
+}
+
+
+char* IoTRMIUtil::charToByteArray(char c, char* bytes) {
+
+       // We need 2 bytes to accommodate Java char type, whose size is 2
+       bytes[0] = 0;
+       bytes[1] = c;
+
+       return bytes;
+}
+
+
+char* IoTRMIUtil::booleanToByteArray(bool b, char* bytes) {
+
+       bytes[0] = (b) ? 1 : 0;
+       return bytes;
+}
+
+
+char* IoTRMIUtil::stringToByteArray(string str, char* bytes) {
+
+       strcpy(bytes, str.c_str());
+       return bytes;
+}
+
+
+// Conversions
+// Byte array to primitives
+short* IoTRMIUtil::byteArrayToShort(short* result, char* bytes) {
+
+       short s = 0;
+       memcpy(&s, bytes, sizeof(short));
+       //short result = be16toh(s);
+       *result = be16toh(s);
+
+       return result;
+}
+
+
+int* IoTRMIUtil::byteArrayToInt(int* result, char* bytes) {
+
+       int i = 0;
+       memcpy(&i, bytes, sizeof(int));
+       *result = be32toh(i);
+
+       return result;
+}
+
+
+int64_t* IoTRMIUtil::byteArrayToLong(int64_t* result, char* bytes) {
+
+       int64_t l = 0;
+       memcpy(&l, bytes, sizeof(int64_t));
+       *result = be64toh(l);
+
+       return result;
+}
+
+
+float* IoTRMIUtil::byteArrayToFloat(float* result, char* bytes) {
+
+       // Copy to int to allow the usage of beXXtoh() functions
+       int i = 0;
+       memcpy(&i, bytes, sizeof(int));
+       int iInvert = be32toh(i);
+       memcpy(result, &iInvert, sizeof(float));
+
+       return result;
+}
+
+
+double* IoTRMIUtil::byteArrayToDouble(double* result, char* bytes) {
+
+       // Copy to int to allow the usage of beXXtoh() functions
+       int64_t i = 0;
+       memcpy(&i, bytes, sizeof(int64_t));
+       int64_t iInvert = be64toh(i);
+       memcpy(result, &iInvert, sizeof(double));
+
+       return result;
+}
+
+
+char* IoTRMIUtil::byteArrayToChar(char* result, char* bytes) {
+
+       *result = bytes[1];
+       return result;
+}
+
+
+bool* IoTRMIUtil::byteArrayToBoolean(bool* result, char* bytes) {
+
+       *result = (bytes[0]) ? true : false;
+       return result;
+}
+
+
+string* IoTRMIUtil::byteArrayToString(string* result, char* bytes) {
+
+       *result= string(bytes);
+       return result;
+}
+
+#endif
diff --git a/iotjava/iotrmi/C++/IoTSocket.hpp b/iotjava/iotrmi/C++/IoTSocket.hpp
new file mode 100644 (file)
index 0000000..46685f7
--- /dev/null
@@ -0,0 +1,211 @@
+/** Class IoTSocket is a base class for IoTSocketServer.cpp
+ *  and IoTSocketClient.cpp that provide interfaces to connect 
+ *  to either Java or C++ socket endpoint
+ *  <p>
+ *  Adapted from Java/C++ socket implementation
+ *  by Keith Vertanen
+ *  @see        <a href="https://www.keithv.com/software/socket/</a>
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-10-17
+ */
+#ifndef _IOTSOCKET_HPP__
+#define _IOTSOCKET_HPP__
+
+// Adds in the send/recv acks after each message.
+#define DEBUG_ACK
+
+static const int SOCKET_BUFF_SIZE = 64000;
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+// Duplicated from winsock2.h
+#define SD_RECEIVE      0x00
+#define SD_SEND         0x01
+#define SD_BOTH         0x02
+
+
+class IoTSocket {
+       public:
+               IoTSocket(int iPort, bool* pResult);
+               ~IoTSocket();
+
+               bool                            close();                                                                // Close the socket
+               bool                            sendBytes(char* pVals, int _iLen);              // Send a set of bytes
+               char*                           receiveBytes(char* pVals, int* len);    // Receive a set of bytes
+
+       protected:              
+               int                                     m_iPort;                                                        // Port I'm listening on
+               int                                     m_iSock;                                                        // Socket connection
+               struct sockaddr_in      m_addrRemote;                                           // Connector's address information
+               double*                         m_pBuffer;                                                      // Reuse the same memory for buffer
+
+       private:
+               bool                            receiveAck();
+               bool                            sendAck();
+};
+
+
+// Constructor
+IoTSocket::IoTSocket(int iPort, bool* pResult) {
+
+       m_iPort         = iPort;
+       m_iSock         = -1;
+       m_pBuffer       = NULL;
+
+       // Allocate our temporary buffers that are used to convert data types
+       m_pBuffer = (double *) malloc(sizeof(double) * SOCKET_BUFF_SIZE);
+       if (!m_pBuffer) {
+               perror("IoTSocket: Failed to malloc buffer!");
+               return;
+       }
+
+}
+
+
+// Destructor
+IoTSocket::~IoTSocket() {
+
+       if (m_pBuffer) {
+               free(m_pBuffer);
+               m_pBuffer = NULL;
+       }
+}
+
+
+// Send bytes over the wire
+bool IoTSocket::sendBytes(char* pVals, int _iLen) {
+
+       int i = 0;
+       int size[1];
+       int iLen = _iLen;
+       size[0] = iLen;
+
+       if (send(m_iSock, size, 1, 0) == -1) {
+               perror("IoTSocket: Send size error!");
+               return false;
+       }
+
+       if (send(m_iSock, (char *) pVals, iLen, 0) == -1) {
+               perror("IoTSocket: Send bytes error!");
+               return false;
+       }
+#ifdef DEBUG_ACK
+       if (!receiveAck())
+               return false;
+       if (!sendAck())
+               return false;
+#endif
+
+       return true;
+}
+
+
+// Receive bytes, returns number of bytes received
+// Generate an array of char on the heap and return it
+char* IoTSocket::receiveBytes(char* pVals, int* len)
+{
+       int                     i                               = 0;
+       int                     j                               = 0;
+       char*           pTemp                   = NULL;
+       int                     iTotalBytes             = 0;
+       int                     iNumBytes               = 0;
+       bool            bEnd                    = false;
+
+       int iTotal = 0;
+       int iResult = 0;
+       char size[1];
+       while ((iTotal < 1) && (iResult != -1)) {
+               iResult = recv(m_iSock, size, 1, 0);    
+               iTotal += iResult;
+       }
+       if (iResult == -1) {
+               perror("IoTSocket: Receive size error!");
+               return NULL;
+       }
+       int iLen = (int) size[0];
+       // To be returned from this method...
+       *len = iLen;
+       pVals = new char[iLen];
+       pTemp = (char *) m_pBuffer;
+       // We receiving the incoming ints one byte at a time.
+       while (!bEnd) {
+               if ((iNumBytes = recv(m_iSock, pTemp, SOCKET_BUFF_SIZE, 0)) == -1) {
+                       perror("IoTSocket: Receive error!");
+                       return NULL;
+               }
+               for (i = 0; i < iNumBytes; i++) {
+                       pVals[j] = pTemp[i];
+                       j++;
+               }
+               iTotalBytes += iNumBytes;
+               if (iTotalBytes == iLen)
+                       bEnd = true;
+       }
+#ifdef DEBUG_ACK
+       if (!sendAck())
+               return NULL;
+       if (!receiveAck())
+               return NULL;
+#endif
+
+       return pVals;
+}
+
+
+// Shut down the socket
+bool IoTSocket::close()
+{
+       if (shutdown(m_iSock, SD_BOTH) == -1) {
+               perror("IoTSocket: Close error!");
+               return false;
+       }
+
+       return true;
+}
+
+
+// Receive a short ack from the client 
+bool IoTSocket::receiveAck()
+{
+       char temp[1];
+       int iTotal = 0;
+       int iResult = 0;
+       while ((iTotal < 1) && (iResult != -1)) {
+
+               iResult = recv(m_iSock, temp, 1, 0);    
+               iTotal += iResult;
+       }
+       if (iResult == -1) {
+
+               perror("IoTSocket: ReceiveAck error!");
+               return false;
+       }
+
+       return true;
+}      
+
+
+// Send a short ack to the client 
+bool IoTSocket::sendAck()
+{
+       char temp[1];
+       temp[0] = 42;
+
+       if (send(m_iSock, temp, 1, 0) == -1)
+               return false;
+       return true;
+}
+
+#endif
diff --git a/iotjava/iotrmi/C++/IoTSocketClient.hpp b/iotjava/iotrmi/C++/IoTSocketClient.hpp
new file mode 100644 (file)
index 0000000..dd5d377
--- /dev/null
@@ -0,0 +1,82 @@
+/** Class IoTSocketClient is a communication class
+ *  that provides interfaces to connect to either
+ *  Java or C++ socket endpoint. It inherits the
+ *  methods from IoTSocket.
+ *  <p>
+ *  Adapted from Java/C++ socket implementation
+ *  by Keith Vertanen
+ *  @see        <a href="https://www.keithv.com/software/socket/</a>
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-08-17
+ */
+#ifndef _IOTSOCKETCLIENT_HPP__
+#define _IOTSOCKETCLIENT_HPP__
+
+#include "IoTSocket.hpp"
+
+class IoTSocketClient : public IoTSocket
+{
+       public:
+               IoTSocketClient(int iPort, const char* pStrHost, bool bReverse, bool* pResult);
+};
+
+
+// Constructor
+IoTSocketClient::IoTSocketClient(int iPort, const char* pStrHost, bool bReverse, bool* pResult) :
+       IoTSocket(iPort, pResult) {
+
+       struct hostent* he = NULL;
+
+       if (pResult)
+               *pResult = false;
+
+       if ((he = gethostbyname(pStrHost)) == NULL) {
+
+               perror("IoTSocketClient: Gethostbyname error!");
+               return;
+       }
+
+       if ((m_iSock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+
+               perror("IoTSocketClient: Socket error!");
+               return;
+       }
+
+       m_addrRemote.sin_family         = AF_INET;        
+       m_addrRemote.sin_port           = htons(m_iPort);      
+       m_addrRemote.sin_addr           = *((struct in_addr *) he->h_addr); 
+       memset(&(m_addrRemote.sin_zero), 0, 8);
+
+       if (connect(m_iSock, (struct sockaddr *) &m_addrRemote, sizeof(struct sockaddr)) == -1) {
+
+               perror("IoTSocketClient: Connect m_iSock error!");
+               return;
+       }
+
+       // Send out request for reversed bits or not
+       char temp[1];
+       if (bReverse) {
+
+               temp[0] = 1;
+               if (send(m_iSock, temp, 1, 0) == -1)
+               {
+                       perror("IoTSocketClient: Send 1 error!");
+                       return;
+               }
+       } else {
+               temp[0] = 0;
+               if (send(m_iSock, temp, 1, 0) == -1)
+               {
+                       perror("IoTSocketClient: Send 2 error!");
+                       return;
+               }
+       }
+       
+       if (pResult)
+               *pResult = true;
+}
+
+
+#endif
diff --git a/iotjava/iotrmi/C++/IoTSocketServer.hpp b/iotjava/iotrmi/C++/IoTSocketServer.hpp
new file mode 100644 (file)
index 0000000..3d56e70
--- /dev/null
@@ -0,0 +1,112 @@
+/** Class IoTSocketServer is a communication class
+ *  that provides interfaces to connect to either
+ *  Java or C++ socket endpoint. It inherits the
+ *  methods from IoTSocket.
+ *  <p>
+ *  Adapted from Java/C++ socket implementation
+ *  by Keith Vertanen
+ *  @see        <a href="https://www.keithv.com/software/socket/</a>
+ *
+ * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version     1.0
+ * @since       2016-08-17
+ */
+#ifndef _IOTSOCKETSERVER_HPP__
+#define _IOTSOCKETSERVER_HPP__
+
+#include "IoTSocket.hpp"
+
+#define BACKLOG 10      // How many pending connections queue will hold 
+
+class IoTSocketServer : public IoTSocket
+{
+  public:
+               IoTSocketServer(int iPort, bool* pResult);
+
+               bool                            connect();                                                      // Accept a new connection
+
+       protected:              
+               bool                            m_bReverse;                                                     // Am I reversing byte order or not?
+               int                                     m_iListen;                                                      // Descriptor we are listening on
+               struct sockaddr_in      m_addrMe;                                                       // My address information
+};
+
+
+// Constructor
+IoTSocketServer::IoTSocketServer(int iPort, bool* pResult) :
+       IoTSocket(iPort, pResult) {
+
+       m_iListen               = -1;
+
+       if (pResult)
+               *pResult = false;
+
+       if ((m_iListen = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+       {
+               perror("IoTSocketServer: Socket error!");
+               return;
+       }
+
+       m_addrMe.sin_family                     = AF_INET;          // Host byte order 
+       m_addrMe.sin_port                       = htons(m_iPort);       // Short, network byte order 
+       m_addrMe.sin_addr.s_addr        = INADDR_ANY;           // Auto-fill with my IP 
+       memset(&(m_addrMe.sin_zero), 0, 8);                             // Zero the rest of the struct 
+
+       if (bind(m_iListen, (struct sockaddr *) &m_addrMe, sizeof(struct sockaddr)) == -1) 
+       {
+               // Note, this can fail if the server has just been shutdown and not enough time has elapsed.
+               // See: http://www.developerweb.net/forum/showthread.php?t=2977 
+               perror("IoTSocketServer: Bind error!");
+               return;
+       }
+
+       if (listen(m_iListen, BACKLOG) == -1) 
+       {
+               perror("IoTSocketServer: Listen error!");
+               return;
+       }
+
+       if (pResult)
+               *pResult = true;
+}
+
+
+// Wait for somebody to connect to us on our port.
+bool IoTSocketServer::connect()
+{
+       socklen_t iSinSize = (socklen_t) sizeof(struct sockaddr_in);
+
+       if ((m_iSock = accept(m_iListen, (struct sockaddr *) &m_addrRemote, &iSinSize)) == -1) 
+       {
+               perror("IoTSocketServer: Accept connection error!");
+               return false;
+       }
+       // The client sends us an int to indicate if we should
+       // be reversing byte order on this connection.  The client 
+       // is sending 0 or 1, so a reversed 0 still looks
+       // like a 0, no worries mate!
+       char temp[1];
+       int iTotal = 0;
+       int iResult = 0;
+       while ((iTotal < 1) && (iResult != -1))
+       {
+               iResult = recv(m_iSock, temp, 1, 0);
+               iTotal += iResult;
+       }
+       if (iResult == -1)
+       {
+               perror("IoTSocketServer: Receive data error!");
+               return false;
+       }
+
+       int iVal = temp[0];
+
+       if (iVal == 0) 
+               m_bReverse = false;
+       else 
+               m_bReverse = true;
+
+       return true;
+}
+
+#endif
diff --git a/iotjava/iotrmi/C++/TestClass.hpp b/iotjava/iotrmi/C++/TestClass.hpp
new file mode 100644 (file)
index 0000000..8d3a3c9
--- /dev/null
@@ -0,0 +1,101 @@
+#include <iostream>
+
+using namespace std;
+
+class TestClass {
+       public:
+               TestClass();
+               TestClass(int _int, float _float, string _string);
+               ~TestClass();
+
+               void                            setA(int _int);
+               void                            setB(float _float);
+               void                            setC(string _string);
+               string                          sumArray(const string newA[]);
+               int                                     setAndGetA(int newA);
+               int                                     setACAndGetA(string newC, int newA);
+               //void                          registerCallback(CallBackInterface _cb);
+               //int                           callBack();
+
+       private:                
+               int                                     intA;
+               float                           floatB;
+               string                          stringC;
+               //CallBackInterface cb;
+
+};
+
+
+TestClass::TestClass() {
+
+       intA = 1;
+       floatB = 2;
+       stringC = "345";
+       //cb = NULL;
+}
+
+
+TestClass::TestClass(int _int, float _float, string _string) {
+
+       intA = _int;
+       floatB = _float;
+       stringC = _string;
+       //cb = NULL;
+}
+
+
+void TestClass::setA(int _int) {
+
+       intA = _int;
+}
+
+
+void TestClass::setB(float _float) {
+
+       floatB = _float;
+}
+
+
+void TestClass::setC(string _string) {
+
+       stringC = _string;
+}
+
+
+string TestClass::sumArray(const string newA[]) {
+
+       string sum = "";
+       int len = sizeof(newA) / sizeof(string);
+       for(int c = 0; c < len; c++) {
+               sum = sum + newA[c];
+       }
+       return sum;
+}
+
+
+int TestClass::setAndGetA(int newA) {
+
+       intA = newA;
+       return intA;
+}
+
+
+int TestClass::setACAndGetA(string newC, int newA) {
+
+       stringC = newC;
+       intA = newA;
+       return intA;
+}
+
+
+/*void TestClass::registerCallback(CallBackInterface _cb) {
+
+       cb = _cb;
+}
+
+
+int TestClass::callBack() {
+
+       return cb.printInt();
+}*/
+
index 9353f336159b5a8652e7f7da896a90ea11a7a7ea..2f21c72dee6a3bea6d2c1a967fab4ac5d0a61b52 100644 (file)
@@ -85,12 +85,12 @@ public class IoTRMICall {
                int numbParam = paramObj.length;
                int methodLen = IoTRMIUtil.METHOD_ID_LEN;       // Initialized to the length of method ID
                byte[][] objBytesArr = new byte[numbParam][];
                int numbParam = paramObj.length;
                int methodLen = IoTRMIUtil.METHOD_ID_LEN;       // Initialized to the length of method ID
                byte[][] objBytesArr = new byte[numbParam][];
-               for (int i=0; i < numbParam; i++) {
+               for (int i = 0; i < numbParam; i++) {
                        // Get byte arrays for the objects
                        objBytesArr[i] = IoTRMIUtil.getObjectBytes(paramObj[i]);
                        String clsName = paramCls[i].getSimpleName();
                        int paramLen = rmiUtil.getTypeSize(clsName);
                        // Get byte arrays for the objects
                        objBytesArr[i] = IoTRMIUtil.getObjectBytes(paramObj[i]);
                        String clsName = paramCls[i].getSimpleName();
                        int paramLen = rmiUtil.getTypeSize(clsName);
-                       if (paramLen == -1) {           // indefinite length
+                       if (paramLen == -1) {           // indefinite length - store the length first
                                methodLen = methodLen + IoTRMIUtil.PARAM_LEN;
                        }
                        methodLen = methodLen + objBytesArr[i].length;
                                methodLen = methodLen + IoTRMIUtil.PARAM_LEN;
                        }
                        methodLen = methodLen + objBytesArr[i].length;
@@ -102,7 +102,7 @@ public class IoTRMICall {
                System.arraycopy(methodId, 0, method, 0, methodId.length);
                pos = pos + IoTRMIUtil.METHOD_ID_LEN;
                // Second iteration for copying bytes
                System.arraycopy(methodId, 0, method, 0, methodId.length);
                pos = pos + IoTRMIUtil.METHOD_ID_LEN;
                // Second iteration for copying bytes
-               for (int i=0; i < numbParam; i++) {
+               for (int i = 0; i < numbParam; i++) {
 
                        String clsName = paramCls[i].getSimpleName();
                        int paramLen = rmiUtil.getTypeSize(clsName);
 
                        String clsName = paramCls[i].getSimpleName();
                        int paramLen = rmiUtil.getTypeSize(clsName);
index c8fefa41d8dbb080dae3dfce93efe9673da119d5..bb093a999c52f0b88c7f4f42816f55262a016a75 100644 (file)
@@ -76,10 +76,10 @@ public class IoTRMIObject {
         */
        public String getSignature() {
 
         */
        public String getSignature() {
 
-               // Get method ID
+               // Get method Id bytes
                byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
                System.arraycopy(methodBytes, 0, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
                byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
                System.arraycopy(methodBytes, 0, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
-               // Get Method object to handle method
+               // Get method Id
                int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
                // Get method signature from the Map
                return mapHash2Sign.get(methodId);
                int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
                // Get method signature from the Map
                return mapHash2Sign.get(methodId);
index 50965ba3b0aed78c29eee897fdc601c9b5b5ddf9..a3e6b54de71fa16c28b7997b7b5e5d209ebffc7f 100644 (file)
@@ -1306,4 +1306,23 @@ public class IoTRMIUtil {
         }
         return obj;
     }
         }
         return obj;
     }
+
+
+       public static void main(String[] args) {
+
+               boolean data = false;
+               //char data = 'c';
+               //float data = 12.5123f;
+               //double data = 12.51231234;
+               //long data = 123456781234l;
+               //short data = 1234;
+               //int data = 12345678;
+               byte[] result = booleanToByteArray(data);
+               System.out.println("Result: " + Arrays.toString(result));
+               System.out.println("Converted back: " + byteArrayToBoolean(result));
+               
+               String str = "methodA(int,string,float,double,double)";
+               int hash = str.hashCode();
+               System.out.println("Hash value: " + hash);
+       }
 }
 }
index 0b9f408e1d9f06e26818fc83022e49ec6f45d46f..1d519dd1c253b064d1459f6204a97b32f7716dc1 100644 (file)
@@ -29,6 +29,7 @@ public class TestClass {
                intA = _int;
                floatB = _float;
                stringC = _string;
                intA = _int;
                floatB = _float;
                stringC = _string;
+               cb = null;
        }
 
 
        }
 
 
@@ -83,7 +84,6 @@ public class TestClass {
 
        public int callBack() {
 
 
        public int callBack() {
 
-               System.out.println("This callBack function is called inside TestClass!");
                return cb.printInt();
        }
 
                return cb.printInt();
        }