Adding premature C++ side; supporting only primitive types (including string) for now
[iot2.git] / iotjava / iotrmi / C++ / IoTRMIObject.hpp
1 /** Class IoTRMIObject 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 skeleton part of the RMI
6  *  communication. It instatiate an RMI object and activate
7  *  a server process that handles RMI requests.
8  *
9  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
10  * @version     1.0
11  * @since       2016-10-24
12  */
13 #ifndef _IOTRMIOBJECT_HPP__
14 #define _IOTRMIOBJECT_HPP__
15
16 #include <iostream>
17 #include <string>
18 #include "IoTRMIUtil.hpp"
19 #include "IoTSocketServer.hpp"
20
21 using namespace std;
22
23 class IoTRMIObject {
24         public:
25                 IoTRMIObject(int _port, bool* _bResult, string _methodSign[], int _size);
26                 ~IoTRMIObject();
27                 // Public methods
28                 void            sendReturnObj(void* retObj, string type);
29                 void            getMethodBytes();
30                 string          getSignature();
31                 void**          getMethodParams(string paramCls[], int numParam, void* paramObj[]);
32
33         private:
34                 map<int,string>         mapHash2Sign;
35                 IoTRMIUtil                      *rmiUtil;
36                 IoTSocketServer         *rmiServer;
37                 char*                           methodBytes;
38                 int                                     methodLen;
39
40                 // Private methods
41                 void                            getMethodIds(string methodSign[], int size);
42 };
43
44
45 // Constructor
46 IoTRMIObject::IoTRMIObject(int _port, bool* _bResult, string _methodSign[], int _size) {
47
48         rmiUtil = new IoTRMIUtil();
49         if (rmiUtil == NULL) {
50                 perror("IoTRMIObject: IoTRMIUtil isn't initialized!");
51         }
52
53         methodBytes = NULL;
54         methodLen = 0;
55         getMethodIds(_methodSign, _size);
56
57         rmiServer = new IoTSocketServer(_port, _bResult);
58         if (rmiServer == NULL) {
59                 perror("IoTRMIObject: IoTSocketServer isn't initialized!");
60         }
61         fflush(NULL);
62         rmiServer->connect();
63         fflush(NULL);
64 }
65
66
67 // Destructor
68 IoTRMIObject::~IoTRMIObject() {
69
70         // Clean up
71         if (rmiUtil != NULL) {
72                 
73                 delete rmiUtil;
74                 rmiUtil = NULL;         
75         }
76         if (rmiServer != NULL) {
77
78                 fflush(NULL);
79                 rmiServer->close();     
80                 delete rmiServer;
81                 rmiServer = NULL;               
82         }
83 }
84
85
86 // Send return values in bytes to the caller
87 void IoTRMIObject::sendReturnObj(void* retObj, string type) {
88
89         // Find the length of return object in bytes
90         int retLen = rmiUtil->getTypeSize(type);
91         if (retLen == -1) {
92                 if (type.compare("string") == 0) {
93                         // Get the length of the string through void* casting to string*
94                         retLen = (*(string*)retObj).length();
95                 }
96         }
97         // Need object bytes variable
98         char retObjBytes[retLen];
99         IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
100         rmiServer->sendBytes(retObjBytes, retLen);
101 }
102
103
104 // Get method bytes from the socket
105 void IoTRMIObject::getMethodBytes() {
106
107         // Get method in bytes and update method length
108         methodBytes = rmiServer->receiveBytes(methodBytes, &methodLen);
109         fflush(NULL);
110         IoTRMIUtil::printBytes(methodBytes, methodLen, false);
111 }
112
113
114 // Get signature from the method-Id-to-method-signature map
115 string IoTRMIObject::getSignature() {
116
117         // Get method Id
118         char methodIdBytes[IoTRMIUtil::METHOD_ID_LEN];
119         memcpy(methodIdBytes, methodBytes, IoTRMIUtil::METHOD_ID_LEN);
120         // Get method object 
121         int methodId = 0;
122         IoTRMIUtil::byteArrayToInt(&methodId, methodIdBytes);
123         cout << "Method Id: " << methodId << endl;
124         
125         return mapHash2Sign.find(methodId)->second;
126 }
127
128
129 // Get method parameters and return an array of parameter objects
130 //
131 // For primitive objects:
132 // | 32-bit method ID | m-bit actual data (fixed length)  |
133 // 
134 // For string, arrays, and non-primitive objects:
135 // | 32-bit method ID | 32-bit length | n-bit actual data | ...
136 void** IoTRMIObject::getMethodParams(string paramCls[], int numParam, void* paramObj[]) {
137
138         // Byte scanning position
139         int pos = IoTRMIUtil::METHOD_ID_LEN;
140         for (int i = 0; i < numParam; i++) {
141
142                 int paramLen = rmiUtil->getTypeSize(paramCls[i]);
143                 // Get the 32-bit field in the byte array to get the actual
144                 //              length (this is a param with indefinite length)
145                 if (paramLen == -1) {
146                         char bytPrmLen[IoTRMIUtil::PARAM_LEN];
147                         memcpy(bytPrmLen, methodBytes + pos, IoTRMIUtil::PARAM_LEN);
148                         pos = pos + IoTRMIUtil::PARAM_LEN;
149                         int* prmLenPtr = IoTRMIUtil::byteArrayToInt(&paramLen, bytPrmLen);
150                         paramLen = *prmLenPtr;
151                 }
152                 char paramBytes[paramLen];
153                 memcpy(paramBytes, methodBytes + pos, paramLen);
154                 pos = pos + paramLen;
155                 paramObj[i] = IoTRMIUtil::getParamObject(paramObj[i], paramCls[i].c_str(), paramBytes);
156
157         }
158         // Delete methodBytes
159         delete[] methodBytes;
160
161         return paramObj;
162 }
163
164
165 // *************
166 //    Helpers
167 // *************
168 void IoTRMIObject::getMethodIds(string methodSign[], int size) {
169
170         for(int i = 0; i < size; i++) {
171                 int methodId = IoTRMIUtil::hashCode(methodSign[i]);
172                 mapHash2Sign[methodId] = methodSign[i];
173         }
174 }
175
176
177 #endif
178
179