77804cdda37afa1b2e2dc198e607262cc9214ac4
[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                 //void                          waitForPackets();
34                 //void                          waitForPackets(IoTRMICommClient* rmiComm);
35
36         private:
37                 IoTSocketClient         *rmiClientSend;
38                 IoTSocketClient         *rmiClientRecv;
39
40                 // Private methods
41                 void                            waitForPackets(IoTRMICommClient* rmiComm);
42 };
43
44
45 // Constructor
46 IoTRMICommClient::IoTRMICommClient(int _portSend, int _portRecv, const char* _address, int _rev, bool* _bResult) : IoTRMIComm() {
47
48         rmiClientRecv = new IoTSocketClient(_portSend, _address, _rev, _bResult);
49         rmiClientSend = new IoTSocketClient(_portRecv, _address, _rev, _bResult);
50         thread th1 (&IoTRMICommClient::waitForPackets, this, this);
51         th1.detach();
52
53 }
54
55
56 // Destructor
57 IoTRMICommClient::~IoTRMICommClient() {
58
59         // Clean up
60         if (rmiClientRecv != NULL) {    
61                 delete rmiClientRecv;
62                 rmiClientRecv = NULL;           
63         }
64         if (rmiClientSend != NULL) {    
65                 delete rmiClientSend;
66                 rmiClientSend = NULL;           
67         }
68 }
69
70
71 void IoTRMICommClient::waitForPackets(IoTRMICommClient* rmiComm) {
72
73         char* packetBytes = NULL;
74         int packetLen = 0;
75         while(true) {
76                 fflush(NULL);
77                 packetBytes = rmiClientRecv->receiveBytes(packetBytes, &packetLen);
78                 fflush(NULL);
79                 if (packetBytes != NULL) { // If there is method bytes
80                         //IoTRMIUtil::printBytes(packetBytes, packetLen, false);
81                         //packetBytesPtr = &packetBytes;
82                         int packetType = getPacketType(packetBytes);
83                         if (packetType == IoTRMIUtil::METHOD_TYPE) {
84                                 rmiComm->methodQueue.enqueue(packetBytes, packetLen);
85                         } else if (packetType == IoTRMIUtil::RET_VAL_TYPE) {
86                                 rmiComm->returnQueue.enqueue(packetBytes, packetLen);
87                         } else {
88                                 // TODO: We need to log error message when we come to running this using IoTSlave
89                                 // TODO: Beware that using "cout" in the process will kill it (as IoTSlave is loaded at runtime)
90                                 cerr << "IoTRMICommClient: Packet type is unknown: " << packetType << endl;
91                                 exit(1);
92                         }
93                 }
94                 packetBytes = NULL;
95                 packetLen = 0;
96         }
97 }
98
99
100 // Send return values in bytes to the caller
101 void IoTRMICommClient::sendReturnObj(void* retObj, string type, char* methodBytes) {
102
103         // Critical section that is used by different objects
104         lock_guard<mutex> guard(sendReturnObjMutex);
105         // Find the length of return object in bytes
106         int retLen = rmiUtil->getTypeSize(type);
107         if (retLen == -1) {
108                 retLen = rmiUtil->getVarTypeSize(type, retObj);
109         }
110         // Copy the header and object bytes
111         int objAndMethIdLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
112         int headerLen = objAndMethIdLen + IoTRMIUtil::PACKET_TYPE_LEN;
113         char retAllObjBytes[headerLen+retLen];
114         // Copy object and method Id first
115         memcpy(retAllObjBytes, methodBytes, objAndMethIdLen);
116         // Copy objectId + methodId + packet type in bytes
117         char packType[IoTRMIUtil::PACKET_TYPE_LEN];
118         IoTRMIUtil::intToByteArray(IoTRMIUtil::RET_VAL_TYPE, packType);
119         memcpy(retAllObjBytes + objAndMethIdLen, packType, IoTRMIUtil::PACKET_TYPE_LEN);
120         // Copy object into byte array
121         char retObjBytes[retLen];
122         IoTRMIUtil::getObjectBytes(retObjBytes, retObj, type.c_str());
123         memcpy(retAllObjBytes + headerLen, retObjBytes, retLen);
124         fflush(NULL);
125         rmiClientSend->sendBytes(retAllObjBytes, headerLen+retLen);
126         fflush(NULL);
127 }
128
129
130 // Send return values in bytes to the caller (for more than one object - struct)
131 void IoTRMICommClient::sendReturnObj(void* retObj[], string type[], int numRet, char* methodBytes) {
132
133         // Critical section that is used by different objects
134         lock_guard<mutex> guard(sendReturnObjMutex);
135         // Find the length of return object in bytes
136         int retLen = returnLength(retObj, type, numRet);
137         // Copy the header and object bytes
138         int objAndMethIdLen = IoTRMIUtil::OBJECT_ID_LEN + IoTRMIUtil::METHOD_ID_LEN;
139         int headerLen = objAndMethIdLen + IoTRMIUtil::PACKET_TYPE_LEN;
140         char retAllObjBytes[headerLen+retLen];
141         // Copy object and method Id first
142         memcpy(retAllObjBytes, methodBytes, objAndMethIdLen);
143         // Copy objectId + methodId + packet type in bytes
144         char packType[IoTRMIUtil::PACKET_TYPE_LEN];
145         IoTRMIUtil::intToByteArray(IoTRMIUtil::RET_VAL_TYPE, packType);
146         memcpy(retAllObjBytes + objAndMethIdLen, packType, IoTRMIUtil::PACKET_TYPE_LEN);
147         // Copy object into byte array
148         char retObjBytes[retLen];
149         returnToBytes(retObj, type, retObjBytes, numRet);
150         memcpy(retAllObjBytes + headerLen, retObjBytes, retLen);
151         fflush(NULL);
152         rmiClientSend->sendBytes(retAllObjBytes, headerLen+retLen);
153         fflush(NULL);
154 }
155
156
157 // Calls a method remotely by passing in parameters and getting a return object
158 void IoTRMICommClient::remoteCall(int objectId, int methodId, string paramCls[], 
159                 void* paramObj[], int numParam) {
160
161         // Critical section that is used by different objects
162         lock_guard<mutex> guard(remoteCallMutex);
163         // Send input parameters
164         int len = methodLength(paramCls, paramObj, numParam);
165         char method[len];
166         methodToBytes(objectId, methodId, paramCls, paramObj, method, numParam);
167         // Send bytes
168         fflush(NULL);
169         rmiClientSend->sendBytes(method, len);
170         fflush(NULL);
171
172 }
173 #endif
174
175