Adding config file for sharing.
[iot2.git] / iotjava / iotrmi / C++ / IoTRMICommClient.hpp
1 /** Class IoTRMICommClient implements the client side
2  *  of IoTRMIComm class.
3  *
4  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
5  * @version     1.0
6  * @since       2017-01-28
7  */
8 #ifndef _IOTRMICOMMCLIENT_HPP__
9 #define _IOTRMICOMMCLIENT_HPP__
10
11 #include <iostream>
12 #include <string>
13 #include <atomic>
14 #include <limits>
15 #include <thread>
16 #include <mutex>
17
18 #include "IoTRMIComm.hpp"
19
20 using namespace std;
21
22 mutex clientRemoteCallMutex;
23 mutex clientSendReturnObjMutex;
24
25 class IoTRMICommClient final : public IoTRMIComm {
26         public:
27                 IoTRMICommClient(int _portSend, int _portRecv, const char* _address, int _rev, bool* _bResult);
28                 ~IoTRMICommClient();
29                 // Public methods
30                 void                            sendReturnObj(void* retObj, string type, char* methodBytes);
31                 void                            sendReturnObj(void* retObj[], string type[], int numRet, char* methodBytes);
32                 void                            remoteCall(int objectId, int methodId, string paramCls[], void* paramObj[], int numParam);
33
34         private:
35                 IoTSocketClient         *rmiClientSend;
36                 IoTSocketClient         *rmiClientRecv;
37
38                 // Private methods
39                 void                            waitForPackets(IoTRMICommClient* rmiComm);
40 };
41
42
43 // Constructor
44 IoTRMICommClient::IoTRMICommClient(int _portSend, int _portRecv, const char* _address, int _rev, bool* _bResult) : IoTRMIComm() {
45
46         rmiClientRecv = new IoTSocketClient(_portSend, _address, _rev, _bResult);
47         rmiClientSend = new IoTSocketClient(_portRecv, _address, _rev, _bResult);
48         thread th1 (&IoTRMICommClient::waitForPackets, this, this);
49         th1.detach();
50 }
51
52
53 // Destructor
54 IoTRMICommClient::~IoTRMICommClient() {
55
56         // Clean up
57         if (rmiClientRecv != NULL) {    
58                 delete rmiClientRecv;
59                 rmiClientRecv = NULL;           
60         }
61         if (rmiClientSend != NULL) {    
62                 delete rmiClientSend;
63                 rmiClientSend = NULL;           
64         }
65 }
66
67
68 void IoTRMICommClient::waitForPackets(IoTRMICommClient* rmiComm) {
69
70         char* packetBytes = NULL;
71         int packetLen = 0;
72         while(true) {
73                 fflush(NULL);
74                 packetBytes = rmiClientRecv->receiveBytes(packetBytes, &packetLen);
75                 fflush(NULL);
76                 if (packetBytes != NULL) { // If there is method bytes
77                         int packetType = getPacketType(packetBytes);
78                         if (packetType == IoTRMIUtil::METHOD_TYPE) {
79                                 rmiComm->methodQueue.enqueue(packetBytes, packetLen);
80                         } else if (packetType == IoTRMIUtil::RET_VAL_TYPE) {
81                                 rmiComm->returnQueue.enqueue(packetBytes, packetLen);
82                         } else {
83                                 // TODO: We need to log error message when we come to running this using IoTSlave
84                                 // TODO: Beware that using "cout" in the process will kill it (as IoTSlave is loaded at runtime)
85                                 cerr << "IoTRMICommClient: Packet type is unknown: " << packetType << endl;
86                                 exit(1);
87                         }
88                 }
89                 packetBytes = NULL;
90                 packetLen = 0;
91         }
92 }
93
94
95 // Send return values in bytes to the caller
96 void IoTRMICommClient::sendReturnObj(void* retObj, string type, char* methodBytes) {
97
98         // Critical section that is used by different objects
99         lock_guard<mutex> guard(sendReturnObjMutex);
100         // Find the length of return object in bytes
101         int retLen = rmiUtil->getTypeSize(type);
102         if (retLen == -1) {
103                 retLen = rmiUtil->getVarTypeSize(type, retObj);
104         }
105         // Copy the header and object bytes
106         int objAndMethIdLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
107         int headerLen = objAndMethIdLen + IoTRMIUtil::PACKET_TYPE_LEN;
108         char retAllObjBytes[headerLen+retLen];
109         // Copy object and method Id first
110         memcpy(retAllObjBytes, methodBytes, objAndMethIdLen);
111         // Copy objectId + methodId + packet type in bytes
112         char packType[IoTRMIUtil::PACKET_TYPE_LEN];
113         IoTRMIUtil::intToByteArray(IoTRMIUtil::RET_VAL_TYPE, packType);
114         memcpy(retAllObjBytes + objAndMethIdLen, packType, IoTRMIUtil::PACKET_TYPE_LEN);
115         // Copy object into byte array
116         char retObjBytes[retLen];
117         IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
118         memcpy(retAllObjBytes + headerLen, retObjBytes, retLen);
119         fflush(NULL);
120         rmiClientSend->sendBytes(retAllObjBytes, headerLen+retLen);
121         fflush(NULL);
122 }
123
124
125 // Send return values in bytes to the caller (for more than one object - struct)
126 void IoTRMICommClient::sendReturnObj(void* retObj[], string type[], int numRet, char* methodBytes) {
127
128         // Critical section that is used by different objects
129         lock_guard<mutex> guard(sendReturnObjMutex);
130         // Find the length of return object in bytes
131         int retLen = returnLength(retObj, type, numRet);
132         // Copy the header and object bytes
133         int objAndMethIdLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
134         int headerLen = objAndMethIdLen + IoTRMIUtil::PACKET_TYPE_LEN;
135         char retAllObjBytes[headerLen+retLen];
136         // Copy object and method Id first
137         memcpy(retAllObjBytes, methodBytes, objAndMethIdLen);
138         // Copy objectId + methodId + packet type in bytes
139         char packType[IoTRMIUtil::PACKET_TYPE_LEN];
140         IoTRMIUtil::intToByteArray(IoTRMIUtil::RET_VAL_TYPE, packType);
141         memcpy(retAllObjBytes + objAndMethIdLen, packType, IoTRMIUtil::PACKET_TYPE_LEN);
142         // Copy object into byte array
143         char retObjBytes[retLen];
144         returnToBytes(retObj, type, retObjBytes, numRet);
145         memcpy(retAllObjBytes + headerLen, retObjBytes, retLen);
146         fflush(NULL);
147         rmiClientSend->sendBytes(retAllObjBytes, headerLen+retLen);
148         fflush(NULL);
149 }
150
151
152 // Calls a method remotely by passing in parameters and getting a return object
153 void IoTRMICommClient::remoteCall(int objectId, int methodId, string paramCls[], 
154                 void* paramObj[], int numParam) {
155
156         // Critical section that is used by different objects
157         lock_guard<mutex> guard(remoteCallMutex);
158         // Send input parameters
159         int len = methodLength(paramCls, paramObj, numParam);
160         char method[len];
161         methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
162         // Send bytes
163         fflush(NULL);
164         rmiClientSend->sendBytes(method, len);
165         fflush(NULL);
166
167 }
168 #endif
169
170