Adding return value support for enumeration (both Java and C++
[iot2.git] / iotjava / iotrmi / C++ / IoTRMICall.hpp
1 /** Class IoTRMICall provides methods that the upper
2  *  layers can use to transport and invoke methods
3  *  when using IoTSocket, IoTSocketClient and IoTSocketServer.
4  *  <p>
5  *  This class serves in the stub part of the RMI
6  *  communication. It bridges and creates RMI requests to be
7  *  transferred into the RMI object.
8  *
9  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
10  * @version     1.0
11  * @since       2016-10-18
12  */
13 #ifndef _IOTRMICALL_HPP__
14 #define _IOTRMICALL_HPP__
15
16 #include <iostream>
17 #include <string>
18 #include <mutex>
19 #include "IoTRMIUtil.hpp"
20 #include "IoTSocketClient.hpp"
21
22 using namespace std;
23
24 mutex mtx;
25
26 class IoTRMICall {
27         public:
28                 IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult);
29                 ~IoTRMICall();
30                 // Public methods
31                 int             methodLength(string paramCls[], void* paramObj[], int numParam);
32                 char*   methodToBytes(int objectId, int methId, string paramCls[], void* paramObj[],
33                                                                 char* method, int numParam);
34                 void*   remoteCall(int objectId, int methodId, string retType, string paramCls[], 
35                                                                 void* paramObj[], int numParam, void* retObj);
36
37         private:
38                 map<string,int>         mapSign2MethodId;
39                 IoTRMIUtil                      *rmiUtil;
40                 IoTSocketClient         *rmiClient;
41
42                 // Private methods
43                 void                            getMethodIds(const string methodSign[], const int size);
44 };
45
46
47 // Constructor
48 IoTRMICall::IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult) {
49
50         rmiUtil = new IoTRMIUtil();
51         if (rmiUtil == NULL) {
52                 perror("IoTRMICall: IoTRMIUtil isn't initialized!");
53         }
54         rmiClient = new IoTSocketClient(_port, _address, _rev, _bResult);
55         if (rmiClient == NULL) {
56                 perror("IoTRMICall: IoTSocketClient isn't initialized!");
57         }
58 }
59
60
61 // Destructor
62 IoTRMICall::~IoTRMICall() {
63
64         // Clean up
65         if (rmiUtil != NULL) {
66                 
67                 delete rmiUtil;
68                 rmiUtil = NULL;         
69         }
70         if (rmiClient != NULL) {
71
72                 fflush(NULL);
73                 rmiClient->close();             
74                 delete rmiClient;
75                 rmiClient = NULL;               
76         }
77 }
78
79
80 // Calls a method remotely by passing in parameters and getting a return object
81 void* IoTRMICall::remoteCall(int objectId, int methodId, string retType, string paramCls[], 
82                                                                 void* paramObj[], int numParam, void* retObj) {
83
84         // Critical section that is used by different objects
85         lock_guard<mutex> guard(mtx);
86         // Send input parameters
87         int len = methodLength(paramCls, paramObj, numParam);
88         char method[len];
89         methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
90 //      IoTRMIUtil::printBytes(method, len, false);
91         // Send bytes
92         fflush(NULL);
93         rmiClient->sendBytes(method, len);
94         fflush(NULL);
95         // Receive return value and return it to caller
96         if (retType.compare("void") == 0)
97                 // Just make it NULL if it's a void return
98                 retObj = NULL;
99         else {
100                 int retLen = 0;
101                 char* retObjBytes = NULL;
102                 retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
103 //              IoTRMIUtil::printBytes(retObjBytes, retLen, false);
104                 retObj = IoTRMIUtil::getParamObject(retObj, retType.c_str(), retObjBytes, retLen);
105         }
106         
107         return retObj;
108 }
109
110
111 // Find the bytes length of a method
112 int IoTRMICall::methodLength(string paramCls[], void* paramObj[], int numParam) {
113
114         // Get byte arrays and calculate method bytes length
115         // Start from the object Id + method Id...
116         int methodLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
117         for (int i = 0; i < numParam; i++) {
118                 // Find the parameter length
119                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
120                 if (paramLen == -1) { // Store the length of the field - indefinite length
121                         paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
122                         // Some space for param length, i.e. 32 bits for integer                
123                         methodLen = methodLen + IoTRMIUtil::PARAM_LEN;
124                 }
125                 // Calculate methodLen
126                 methodLen = methodLen + paramLen;
127         }
128
129         return methodLen;
130 }
131
132
133 // Convert method and its parameters into bytes
134 char* IoTRMICall::methodToBytes(int objectId, int methId, string paramCls[], 
135                 void* paramObj[], char* method, int numParam) {
136
137         // Get object Id in bytes
138         char objId[IoTRMIUtil::OBJECT_ID_LEN];
139         IoTRMIUtil::intToByteArray(objectId, objId);
140         memcpy(method, objId, IoTRMIUtil::OBJECT_ID_LEN);
141         int pos = IoTRMIUtil::OBJECT_ID_LEN;
142         // Get method Id in bytes
143         char methodId[IoTRMIUtil::METHOD_ID_LEN];
144         IoTRMIUtil::intToByteArray(methId, methodId);
145         memcpy(method + pos, methodId, IoTRMIUtil::METHOD_ID_LEN);
146         pos = pos + IoTRMIUtil::METHOD_ID_LEN;
147         // Get byte arrays and calculate method bytes length
148         for (int i = 0; i < numParam; i++) {
149                 // Find the parameter length
150                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
151                 if (paramLen == -1) { // Store the length of the field - indefinite length
152                         paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
153                         // Write the parameter length
154                         char prmLenBytes[IoTRMIUtil::METHOD_ID_LEN];
155                         IoTRMIUtil::intToByteArray(paramLen, prmLenBytes);
156                         memcpy(method + pos, prmLenBytes, IoTRMIUtil::PARAM_LEN);                       
157                         pos = pos + IoTRMIUtil::PARAM_LEN;
158                 }
159                 // Get array of bytes and put it in the array of array of bytes
160                 char objBytes[paramLen];
161                 IoTRMIUtil::getObjectBytes(objBytes, paramObj[i], paramCls[i].c_str());
162                 memcpy(method + pos, objBytes, paramLen);
163                 pos = pos + paramLen;
164         }
165
166         return method;
167 }
168
169 #endif
170
171