From b54e7e1e86dd82c39e3a8fd5ff648283ba98bef6 Mon Sep 17 00:00:00 2001 From: rtrimana Date: Mon, 24 Oct 2016 16:18:35 -0700 Subject: [PATCH] Adding premature C++ side; supporting only primitive types (including string) for now --- common.mk | 1 + iotjava/Makefile | 6 + iotjava/iotrmi/C++/IoTRMICall.hpp | 162 +++++++++ iotjava/iotrmi/C++/IoTRMIObject.hpp | 179 ++++++++++ iotjava/iotrmi/C++/IoTRMITypes.hpp | 193 +++++++++++ iotjava/iotrmi/C++/IoTRMIUtil.hpp | 389 ++++++++++++++++++++++ iotjava/iotrmi/C++/IoTSocket.hpp | 211 ++++++++++++ iotjava/iotrmi/C++/IoTSocketClient.hpp | 82 +++++ iotjava/iotrmi/C++/IoTSocketServer.hpp | 112 +++++++ iotjava/iotrmi/C++/TestClass.hpp | 101 ++++++ iotjava/iotrmi/Java/IoTRMICall.java | 6 +- iotjava/iotrmi/Java/IoTRMIObject.java | 4 +- iotjava/iotrmi/Java/IoTRMIUtil.java | 19 ++ iotjava/iotrmi/Java/sample/TestClass.java | 2 +- 14 files changed, 1461 insertions(+), 6 deletions(-) create mode 100644 iotjava/iotrmi/C++/IoTRMICall.hpp create mode 100644 iotjava/iotrmi/C++/IoTRMIObject.hpp create mode 100644 iotjava/iotrmi/C++/IoTRMITypes.hpp create mode 100644 iotjava/iotrmi/C++/IoTRMIUtil.hpp create mode 100644 iotjava/iotrmi/C++/IoTSocket.hpp create mode 100644 iotjava/iotrmi/C++/IoTSocketClient.hpp create mode 100644 iotjava/iotrmi/C++/IoTSocketServer.hpp create mode 100644 iotjava/iotrmi/C++/TestClass.hpp diff --git a/common.mk b/common.mk index ed6efc9..0b14291 100644 --- a/common.mk +++ b/common.mk @@ -1,3 +1,4 @@ +G++ := g++ JAVA := java JAR := jar JAVADOC := javadoc diff --git a/iotjava/Makefile b/iotjava/Makefile index d9b968f..985e41e 100644 --- a/iotjava/Makefile +++ b/iotjava/Makefile @@ -30,9 +30,15 @@ runtime: # 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 + 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: diff --git a/iotjava/iotrmi/C++/IoTRMICall.hpp b/iotjava/iotrmi/C++/IoTRMICall.hpp new file mode 100644 index 0000000..8503cdf --- /dev/null +++ b/iotjava/iotrmi/C++/IoTRMICall.hpp @@ -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. + *

+ * 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 + * @version 1.0 + * @since 2016-10-18 + */ +#ifndef _IOTRMICALL_HPP__ +#define _IOTRMICALL_HPP__ + +#include +#include +#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 index 0000000..a6e4cb1 --- /dev/null +++ b/iotjava/iotrmi/C++/IoTRMIObject.hpp @@ -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. + *

+ * 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 + * @version 1.0 + * @since 2016-10-24 + */ +#ifndef _IOTRMIOBJECT_HPP__ +#define _IOTRMIOBJECT_HPP__ + +#include +#include +#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 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(¶mLen, 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 index 0000000..2c32f47 --- /dev/null +++ b/iotjava/iotrmi/C++/IoTRMITypes.hpp @@ -0,0 +1,193 @@ +/** Class IoTRMITypes is a class that provides type translations. + *

+ * It stores C++ and Java types. + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-10-18 + */ +#ifndef _IOTRMITYPES_HPP__ +#define _IOTRMITYPES_HPP__ + +#include +#include +#include +#include + +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 &srcMap, const vector arrKey, + const vector arrVal); + static void arraysToMap(map &srcMap, const vector arrKey, + const vector arrVal); + static void arraysToMap(map &srcMap, const vector arrKey, + const vector 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 &srcMap, const vector arrKey, + const vector 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 &srcMap, const vector arrKey, + const vector 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 &srcMap, const vector arrKey, + const vector 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 index 0000000..677612b --- /dev/null +++ b/iotjava/iotrmi/C++/IoTRMIUtil.hpp @@ -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 + * @version 1.0 + * @since 2016-10-18 + */ +#ifndef _IOTRMIUTIL_HPP__ +#define _IOTRMIUTIL_HPP__ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 mapPrimitives; + map mapPrimitiveSizesJava; + map mapPrimitiveSizesCplus; + map mapNonPrimitives; +}; + + +// Constructor +IoTRMIUtil::IoTRMIUtil() { + + // Prepare vectors for inputs + std::vector primJava (IoTRMITypes::primitivesJava, + IoTRMITypes::primitivesJava + sizeof(IoTRMITypes::primitivesJava)/sizeof(string)); + std::vector primCplus (IoTRMITypes::primitivesCplus, + IoTRMITypes::primitivesCplus + sizeof(IoTRMITypes::primitivesCplus)/sizeof(string)); + std::vector primJavaSizes (IoTRMITypes::primitivesJavaSizes, + IoTRMITypes::primitivesJavaSizes + sizeof(IoTRMITypes::primitivesJavaSizes)/sizeof(int)); + std::vector primCplusSizes (IoTRMITypes::primitivesCplusSizes, + IoTRMITypes::primitivesCplusSizes + sizeof(IoTRMITypes::primitivesCplusSizes)/sizeof(int)); + std::vector nonPrimJava (IoTRMITypes::nonPrimitivesJava, + IoTRMITypes::nonPrimitivesJava + sizeof(IoTRMITypes::nonPrimitivesJava)/sizeof(string)); + std::vector 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*) ¶mBytes[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 index 0000000..46685f7 --- /dev/null +++ b/iotjava/iotrmi/C++/IoTSocket.hpp @@ -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 + *

+ * Adapted from Java/C++ socket implementation + * by Keith Vertanen + * @see + * Adapted from Java/C++ socket implementation + * by Keith Vertanen + * @see 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 index 0000000..3d56e70 --- /dev/null +++ b/iotjava/iotrmi/C++/IoTSocketServer.hpp @@ -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. + *

+ * Adapted from Java/C++ socket implementation + * by Keith Vertanen + * @see + +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(); +}*/ + diff --git a/iotjava/iotrmi/Java/IoTRMICall.java b/iotjava/iotrmi/Java/IoTRMICall.java index 9353f33..2f21c72 100644 --- a/iotjava/iotrmi/Java/IoTRMICall.java +++ b/iotjava/iotrmi/Java/IoTRMICall.java @@ -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][]; - 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); - if (paramLen == -1) { // indefinite length + if (paramLen == -1) { // indefinite length - store the length first 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 - for (int i=0; i < numbParam; i++) { + for (int i = 0; i < numbParam; i++) { String clsName = paramCls[i].getSimpleName(); int paramLen = rmiUtil.getTypeSize(clsName); diff --git a/iotjava/iotrmi/Java/IoTRMIObject.java b/iotjava/iotrmi/Java/IoTRMIObject.java index c8fefa4..bb093a9 100644 --- a/iotjava/iotrmi/Java/IoTRMIObject.java +++ b/iotjava/iotrmi/Java/IoTRMIObject.java @@ -76,10 +76,10 @@ public class IoTRMIObject { */ 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); - // Get Method object to handle method + // Get method Id int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes); // Get method signature from the Map return mapHash2Sign.get(methodId); diff --git a/iotjava/iotrmi/Java/IoTRMIUtil.java b/iotjava/iotrmi/Java/IoTRMIUtil.java index 50965ba..a3e6b54 100644 --- a/iotjava/iotrmi/Java/IoTRMIUtil.java +++ b/iotjava/iotrmi/Java/IoTRMIUtil.java @@ -1306,4 +1306,23 @@ public class IoTRMIUtil { } 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); + } } diff --git a/iotjava/iotrmi/Java/sample/TestClass.java b/iotjava/iotrmi/Java/sample/TestClass.java index 0b9f408..1d519dd 100644 --- a/iotjava/iotrmi/Java/sample/TestClass.java +++ b/iotjava/iotrmi/Java/sample/TestClass.java @@ -29,6 +29,7 @@ public class TestClass { intA = _int; floatB = _float; stringC = _string; + cb = null; } @@ -83,7 +84,6 @@ public class TestClass { public int callBack() { - System.out.println("This callBack function is called inside TestClass!"); return cb.printInt(); } -- 2.34.1