Using sorted integer as method Id instead of hash values
[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 "IoTRMIUtil.hpp"
19 #include "IoTSocketClient.hpp"
20
21 using namespace std;
22
23 class IoTRMICall {
24         public:
25                 IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult, string _methodSign[], int _size);
26                 ~IoTRMICall();
27                 // Public methods
28                 int             methodLength(string paramCls[], void* paramObj[], int numParam);
29                 char*   methodToBytes(string methodSign, string paramCls[], void* paramObj[],
30                                                                 char* method, int numParam);
31                 void*   remoteCall(string methodSign, string retType, string paramCls[], 
32                                                                 void* paramObj[], int numParam, void* retObj);
33
34         private:
35                 map<string,int>         mapSign2MethodId;
36                 IoTRMIUtil                      *rmiUtil;
37                 IoTSocketClient         *rmiClient;
38
39                 // Private methods
40                 void                            getMethodIds(string methodSign[], int size);
41 };
42
43
44 // Constructor
45 IoTRMICall::IoTRMICall(int _port, const char* _address, int _rev, bool* _bResult, string _methodSign[], int _size) {
46
47         getMethodIds(_methodSign, _size);
48         rmiUtil = new IoTRMIUtil();
49         if (rmiUtil == NULL) {
50                 perror("IoTRMICall: IoTRMIUtil isn't initialized!");
51         }
52         rmiClient = new IoTSocketClient(_port, _address, _rev, _bResult);
53         if (rmiClient == NULL) {
54                 perror("IoTRMICall: IoTSocketClient isn't initialized!");
55         }
56 }
57
58
59 // Destructor
60 IoTRMICall::~IoTRMICall() {
61
62         // Clean up
63         if (rmiUtil != NULL) {
64                 
65                 delete rmiUtil;
66                 rmiUtil = NULL;         
67         }
68         if (rmiClient != NULL) {
69
70                 fflush(NULL);
71                 rmiClient->close();             
72                 delete rmiClient;
73                 rmiClient = NULL;               
74         }
75 }
76
77
78 // Calls a method remotely by passing in parameters and getting a return object
79 void* IoTRMICall::remoteCall(string methodSign, string retType, string paramCls[], 
80                                                                 void* paramObj[], int numParam, void* retObj) {
81
82         // Send input parameters
83         int len = methodLength(paramCls, paramObj, numParam);
84         char method[len];
85         methodToBytes(methodSign, paramCls, paramObj, method, numParam);
86         // Send bytes
87         fflush(NULL);
88         rmiClient->sendBytes(method, len);
89         fflush(NULL);
90         // Receive return value and return it to caller
91         if (retType.compare("void") == 0)
92                 // Just make it NULL if it's a void return
93                 retObj = NULL;
94         else {
95                 int retLen = 0;
96                 char* retObjBytes = NULL;
97                 retObjBytes = rmiClient->receiveBytes(retObjBytes, &retLen);
98                 IoTRMIUtil::printBytes(retObjBytes, retLen, false);
99                 retObj = IoTRMIUtil::getParamObject(retObj, retType.c_str(), retObjBytes, retLen);
100         }
101         
102         return retObj;
103 }
104
105
106 // Find the bytes length of a method
107 int IoTRMICall::methodLength(string paramCls[], void* paramObj[], int numParam) {
108
109         // Get byte arrays and calculate method bytes length
110         // Start from the method Id...
111         int methodLen = IoTRMIUtil::METHOD_ID_LEN;
112         for (int i = 0; i < numParam; i++) {
113                 // Find the parameter length
114                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
115                 if (paramLen == -1) { // Store the length of the field - indefinite length
116                         paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
117                         // Some space for param length, i.e. 32 bits for integer                
118                         methodLen = methodLen + IoTRMIUtil::PARAM_LEN;
119                 }
120                 // Calculate methodLen
121                 methodLen = methodLen + paramLen;
122         }
123
124         return methodLen;
125 }
126
127
128 // Convert method and its parameters into bytes
129 char* IoTRMICall::methodToBytes(string methodSign, string paramCls[], 
130                 void* paramObj[], char* method, int numParam) {
131
132         // Get method ID in bytes
133         char methodId[IoTRMIUtil::METHOD_ID_LEN];
134         int methId = mapSign2MethodId.find(methodSign)->second;
135         IoTRMIUtil::intToByteArray(methId, methodId);
136         memcpy(method, methodId, IoTRMIUtil::METHOD_ID_LEN);
137         int pos = IoTRMIUtil::METHOD_ID_LEN;
138         // Get byte arrays and calculate method bytes length
139         for (int i = 0; i < numParam; i++) {
140                 // Find the parameter length
141                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
142                 if (paramLen == -1) { // Store the length of the field - indefinite length
143                         paramLen = rmiUtil->getVarTypeSize(paramCls[i], paramObj[i]);
144                         // Write the parameter length
145                         char prmLenBytes[IoTRMIUtil::METHOD_ID_LEN];
146                         IoTRMIUtil::intToByteArray(paramLen, prmLenBytes);
147                         memcpy(method + pos, prmLenBytes, IoTRMIUtil::PARAM_LEN);                       
148                         pos = pos + IoTRMIUtil::PARAM_LEN;
149                 }
150                 // Get array of bytes and put it in the array of array of bytes
151                 char objBytes[paramLen];
152                 IoTRMIUtil::getObjectBytes(objBytes, paramObj[i], paramCls[i].c_str());
153                 memcpy(method + pos, objBytes, paramLen);
154                 pos = pos + paramLen;
155         }
156
157         return method;
158 }
159
160
161 // *************
162 //    Helpers
163 // *************
164 void IoTRMICall::getMethodIds(string methodSign[], int size) {
165
166         for(int i = 0; i < size; i++) {
167                 mapSign2MethodId[methodSign[i]] = i;
168         }
169 }
170
171
172
173 #endif
174
175