1 /** Class IoTRMIObject provides methods that the upper
2 * layers can use to transport and invoke methods
3 * when using IoTSocket, IoTSocketClient and IoTSocketServer.
5 * This class serves in the skeleton part of the RMI
6 * communication. It instatiate an RMI object and activate
7 * a server process that handles RMI requests.
9 * @author Rahmadi Trimananda <rtrimana @ uci.edu>
13 #ifndef _IOTRMIOBJECT_HPP__
14 #define _IOTRMIOBJECT_HPP__
18 #include "IoTRMIUtil.hpp"
19 #include "IoTSocketServer.hpp"
25 IoTRMIObject(int _port, bool* _bResult, string _methodSign[], int _size);
28 void sendReturnObj(void* retObj, string type);
29 void getMethodBytes();
30 string getSignature();
31 void** getMethodParams(string paramCls[], int numParam, void* paramObj[]);
34 map<int,string> mapHash2Sign;
36 IoTSocketServer *rmiServer;
41 void getMethodIds(string methodSign[], int size);
46 IoTRMIObject::IoTRMIObject(int _port, bool* _bResult, string _methodSign[], int _size) {
48 rmiUtil = new IoTRMIUtil();
49 if (rmiUtil == NULL) {
50 perror("IoTRMIObject: IoTRMIUtil isn't initialized!");
55 getMethodIds(_methodSign, _size);
57 rmiServer = new IoTSocketServer(_port, _bResult);
58 if (rmiServer == NULL) {
59 perror("IoTRMIObject: IoTSocketServer isn't initialized!");
68 IoTRMIObject::~IoTRMIObject() {
71 if (rmiUtil != NULL) {
76 if (rmiServer != NULL) {
86 // Send return values in bytes to the caller
87 void IoTRMIObject::sendReturnObj(void* retObj, string type) {
89 // Find the length of return object in bytes
90 int retLen = rmiUtil->getTypeSize(type);
92 if (type.compare("string") == 0) {
93 // Get the length of the string through void* casting to string*
94 retLen = (*(string*)retObj).length();
95 } else if (type.compare("string[]") == 0) {
96 retLen = IoTRMIUtil::getByteStringLength(*(vector<string>*) retObj);
98 string error = "IoTRMICall: Unrecognizable type: " + type;
102 // Need object bytes variable
103 char retObjBytes[retLen];
104 IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
105 rmiServer->sendBytes(retObjBytes, retLen);
109 // Get method bytes from the socket
110 void IoTRMIObject::getMethodBytes() {
112 // Get method in bytes and update method length
113 methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
118 // Get signature from the method-Id-to-method-signature map
119 string IoTRMIObject::getSignature() {
122 char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
123 memcpy(methodIdBytes, methodBytes, IoTRMIUtil::METHOD_ID_LEN);
126 IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
128 return mapHash2Sign.find(methodId)->second;
132 // Get method parameters and return an array of parameter objects
134 // For primitive objects:
135 // | 32-bit method ID | m-bit actual data (fixed length) |
137 // For string, arrays, and non-primitive objects:
138 // | 32-bit method ID | 32-bit length | n-bit actual data | ...
139 void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
141 // Byte scanning position
142 int pos = IoTRMIUtil::METHOD_ID_LEN;
143 for (int i = 0; i < numParam; i++) {
144 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
145 // Get the 32-bit field in the byte array to get the actual
146 // length (this is a param with indefinite length)
147 if (paramLen == -1) {
148 char bytPrmLen[IoTRMIUtil::PARAM_LEN];
149 memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
150 pos = pos + IoTRMIUtil::PARAM_LEN;
151 int* prmLenPtr = IoTRMIUtil::byteArrayToInt(¶mLen, bytPrmLen);
152 paramLen = *prmLenPtr;
154 char paramBytes[paramLen];
155 memcpy(paramBytes, methodBytes + pos, paramLen);
156 pos = pos + paramLen;
157 paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes, paramLen);
159 // Delete methodBytes
160 delete[] methodBytes;
169 void IoTRMIObject::getMethodIds(string methodSign[], int size) {
171 for(int i = 0; i < size; i++) {
172 int methodId = IoTRMIUtil::hashCode(methodSign[i]);
173 mapHash2Sign[methodId] = methodSign[i];