Merge branch 'master' of ssh://plrg.eecs.uci.edu/home/git/iot2
[iot2.git] / iotjava / iotrmi / Java / IoTRMICommClient.java
1 package iotrmi.Java;
2
3 import java.io.IOException;
4 import java.nio.ByteBuffer;
5 import java.util.Arrays;
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11 import java.lang.reflect.*;
12
13 import java.util.concurrent.*;
14 import java.util.concurrent.atomic.AtomicBoolean;
15
16
17 /** Class IoTRMICommClient is a class that extends IoTRMIComm
18  *  <p>
19  *  This is a version of IoTRMIComm that sits on the main stub.
20  *
21  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
22  * @version     1.0
23  * @since       2017-01-27
24  */
25 public final class IoTRMICommClient extends IoTRMIComm {
26
27         /**
28          * Class Properties
29          */
30         private IoTSocketClient rmiClientSend;
31         private IoTSocketClient rmiClientRecv;
32
33
34         /**
35          * Constructor (for stub) - send and recv from the perspective of RMI socket servers
36          */
37         public IoTRMICommClient(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _address, int _rev) throws  
38                 ClassNotFoundException, InstantiationException, 
39                         IllegalAccessException, IOException {
40
41                 super();
42                 rmiClientRecv = new IoTSocketClient(_localPortSend, _portSend, _address, _rev);
43                 rmiClientSend = new IoTSocketClient(_localPortRecv, _portRecv, _address, _rev);
44                 waitForPacketsOnClient();
45         }
46
47
48         /**
49          * Constructor (for stub) - only destination port numbers
50          */
51         public IoTRMICommClient(int _portSend, int _portRecv, String _address, int _rev) throws  
52                 ClassNotFoundException, InstantiationException, 
53                         IllegalAccessException, IOException {
54
55                 super();
56                 rmiClientRecv = new IoTSocketClient(_portSend, _address, _rev);
57                 rmiClientSend = new IoTSocketClient(_portRecv, _address, _rev);
58                 waitForPacketsOnClient();
59         }
60
61
62         /**
63          * waitForPacketsOnClient() starts a thread that waits for packet bytes on client side
64          */
65         public void waitForPacketsOnClient() {
66
67                 Thread thread = new Thread() {
68                         public void run() {
69                                 byte[] packetBytes = null;
70                                 while(true) {
71                                         try {
72                                                 packetBytes = rmiClientRecv.receiveBytes(packetBytes);
73                                                 if (packetBytes != null) {
74                                                         int packetType = IoTRMIComm.getPacketType(packetBytes);
75                                                         if (packetType == IoTRMIUtil.METHOD_TYPE) {
76                                                                 //System.out.println("Method packet: " + Arrays.toString(packetBytes));
77                                                                 methodQueue.offer(packetBytes);
78                                                         } else if (packetType == IoTRMIUtil.RET_VAL_TYPE) {
79                                                                 //System.out.println("Return value packet: " + Arrays.toString(packetBytes));
80                                                                 returnQueue.offer(packetBytes);
81                                                         } else
82                                                                 throw new Error("IoTRMICommClient: Packet type is unknown: " + packetType);
83                                                 } //else
84                                                 //      Thread.sleep(100);
85                                                 packetBytes = null;
86                                         } catch (Exception ex) {
87                                                 ex.printStackTrace();
88                                                 throw new Error("IoTRMICommClient: Error receiving return value bytes on client!");
89                                         }
90                                 }
91                         }
92                 };
93                 thread.start();
94         }
95
96
97         /**
98          * sendReturnObj() for non-struct objects (client side)
99          */
100         public synchronized void sendReturnObj(Object retObj, byte[] methodBytes) {
101
102                 // Send back return value
103                 //byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
104                 byte[] retObjBytes = null;
105                 if (retObj != null)     // Handle nullness
106                         retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
107                 // Send return value together with OBJECT_ID and METHOD_ID for arbitration
108                 int objMethIdLen = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
109                 int headerLen = objMethIdLen + IoTRMIUtil.PACKET_TYPE_LEN;
110                 //byte[] retAllBytes = new byte[headerLen + retObjBytes.length];
111                 byte[] retAllBytes = null;
112                 if (retObj == null)     // Handle nullness
113                         retAllBytes = new byte[headerLen];
114                 else
115                         retAllBytes = new byte[headerLen + retObjBytes.length];
116                 // Copy OBJECT_ID and METHOD_ID
117                 System.arraycopy(methodBytes, 0, retAllBytes, 0, objMethIdLen);
118                 int packetType = IoTRMIUtil.RET_VAL_TYPE;       // This is a return value
119                 byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType);
120                 System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN);
121                 // Copy array of bytes (return object)
122                 if (retObj != null)
123                         System.arraycopy(retObjBytes, 0, retAllBytes, headerLen, retObjBytes.length);
124                 try {
125                         rmiClientSend.sendBytes(retAllBytes);
126                 } catch (IOException ex) {
127                         ex.printStackTrace();
128                         throw new Error("IoTRMICommClient: Error sending bytes in sendReturnObj()!");
129                 }
130         }
131
132
133         /**
134          * sendReturnObj() overloaded to send multiple return objects for structs (client side)
135          */
136         public synchronized void sendReturnObj(Class<?>[] retCls, Object[] retObj, byte[] methodBytes) {
137
138                 // Send back return value
139                 byte[] retObjBytes = returnToBytes(retCls, retObj);
140                 // Send return value together with OBJECT_ID and METHOD_ID for arbitration
141                 int objMethIdLen = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
142                 int headerLen = objMethIdLen + IoTRMIUtil.PACKET_TYPE_LEN;
143                 byte[] retAllBytes = new byte[headerLen + retObjBytes.length];
144                 // Copy OBJECT_ID and METHOD_ID
145                 System.arraycopy(methodBytes, 0, retAllBytes, 0, objMethIdLen);
146                 int packetType = IoTRMIUtil.RET_VAL_TYPE;       // This is a return value
147                 byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType);
148                 System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN);
149                 // Copy array of bytes (return object)
150                 try {
151                         rmiClientSend.sendBytes(retAllBytes);
152                 } catch (IOException ex) {
153                         ex.printStackTrace();
154                         throw new Error("IoTRMICommClient: Error sending bytes in sendReturnObj()!");
155                 }
156         }
157
158
159         /**
160          * remoteCall() calls a method remotely by passing in parameters (client side)
161          */
162         public synchronized void remoteCall(int objectId, int methodId, Class<?>[] paramCls, Object[] paramObj) {
163
164                 // Send method info
165                 byte[] methodBytes = methodToBytes(objectId, methodId, paramCls, paramObj);
166                 try {
167                         rmiClientSend.sendBytes(methodBytes);
168                 } catch (IOException ex) {
169                         ex.printStackTrace();
170                         throw new Error("IoTRMICommClient: Error when sending bytes in remoteCall()!");
171                 }
172         }
173 }