Changing IoTRMIComm into abstract and refactoring into Client and Server parts
[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 class IoTRMICommClient extends IoTRMIComm {
26
27         /**
28          * Class Properties
29          */
30         private IoTSocketClient rmiClientSend;
31         private IoTSocketClient rmiClientRecv;
32         private int objectIdCounter = Integer.MAX_VALUE;
33
34
35         /**
36          * Constructor (for stub) - send and recv from the perspective of RMI socket servers
37          */
38         public IoTRMICommClient(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _address, int _rev) throws  
39                 ClassNotFoundException, InstantiationException, 
40                         IllegalAccessException, IOException {
41
42                 super();
43                 rmiClientRecv = new IoTSocketClient(_localPortSend, _portSend, _address, _rev);
44                 rmiClientSend = new IoTSocketClient(_localPortRecv, _portRecv, _address, _rev);
45                 waitForPacketsOnClient();
46         }
47
48
49         /**
50          * waitForPacketsOnClient() starts a thread that waits for packet bytes on client side
51          */
52         public void waitForPacketsOnClient() {
53
54                 Thread thread = new Thread() {
55                         public void run() {
56                                 byte[] packetBytes = null;
57                                 while(true) {
58                                         try {
59                                                 packetBytes = rmiClientRecv.receiveBytes(packetBytes);
60                                                 if (packetBytes != null) {
61                                                         int packetType = IoTRMIComm.getPacketType(packetBytes);
62                                                         if (packetType == IoTRMIUtil.METHOD_TYPE) {
63                                                                 System.out.println("Method packet: " + Arrays.toString(packetBytes));
64                                                                 methodQueue.offer(packetBytes);
65                                                         } else if (packetType == IoTRMIUtil.RET_VAL_TYPE) {
66                                                                 System.out.println("Return value packet: " + Arrays.toString(packetBytes));
67                                                                 returnQueue.offer(packetBytes);
68                                                         } else
69                                                                 throw new Error("IoTRMIComm: Packet type is unknown: " + packetType);
70                                                 } //else
71                                                 //      Thread.sleep(100);
72                                                 packetBytes = null;
73                                         } catch (Exception ex) {
74                                                 ex.printStackTrace();
75                                                 throw new Error("IoTRMIComm: Error receiving return value bytes on client!");
76                                         }
77                                 }
78                         }
79                 };
80                 thread.start();
81         }
82
83
84         /**
85          * sendReturnObj() for non-struct objects (client side)
86          */
87         public synchronized void sendReturnObj(Object retObj, byte[] methodBytes) {
88
89                 // Send back return value
90                 byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
91                 // Send return value together with OBJECT_ID and METHOD_ID for arbitration
92                 int objMethIdLen = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
93                 int headerLen = objMethIdLen + IoTRMIUtil.PACKET_TYPE_LEN;
94                 byte[] retAllBytes = new byte[headerLen + retObjBytes.length];
95                 // Copy OBJECT_ID and METHOD_ID
96                 System.arraycopy(methodBytes, 0, retAllBytes, 0, objMethIdLen);
97                 int packetType = IoTRMIUtil.RET_VAL_TYPE;       // This is a return value
98                 byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType);
99                 System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN);
100                 // Copy array of bytes (return object)
101                 System.arraycopy(retObjBytes, 0, retAllBytes, headerLen, retObjBytes.length);
102                 try {
103                         rmiClientSend.sendBytes(retAllBytes);
104                 } catch (IOException ex) {
105                         ex.printStackTrace();
106                         throw new Error("IoTRMICommClient: Error sending bytes in sendReturnObj()!");
107                 }
108         }
109
110
111         /**
112          * sendReturnObj() overloaded to send multiple return objects for structs (client side)
113          */
114         public synchronized void sendReturnObj(Class<?>[] retCls, Object[] retObj, byte[] methodBytes) {
115
116                 // Send back return value
117                 byte[] retObjBytes = returnToBytes(retCls, retObj);
118                 // Send return value together with OBJECT_ID and METHOD_ID for arbitration
119                 int objMethIdLen = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
120                 int headerLen = objMethIdLen + IoTRMIUtil.PACKET_TYPE_LEN;
121                 byte[] retAllBytes = new byte[headerLen + retObjBytes.length];
122                 // Copy OBJECT_ID and METHOD_ID
123                 System.arraycopy(methodBytes, 0, retAllBytes, 0, objMethIdLen);
124                 int packetType = IoTRMIUtil.RET_VAL_TYPE;       // This is a return value
125                 byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType);
126                 System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN);
127                 // Copy array of bytes (return object)
128                 try {
129                         rmiClientSend.sendBytes(retAllBytes);
130                 } catch (IOException ex) {
131                         ex.printStackTrace();
132                         throw new Error("IoTRMICommClient: Error sending bytes in sendReturnObj()!");
133                 }
134         }
135
136
137         /**
138          * remoteCall() calls a method remotely by passing in parameters (client side)
139          */
140         public synchronized void remoteCall(int objectId, int methodId, Class<?>[] paramCls, Object[] paramObj) {
141
142                 // Send method info
143                 byte[] methodBytes = methodToBytes(objectId, methodId, paramCls, paramObj);
144                 try {
145                         rmiClientSend.sendBytes(methodBytes);
146                 } catch (IOException ex) {
147                         ex.printStackTrace();
148                         throw new Error("IoTRMICommClient: Error when sending bytes in remoteCall()!");
149                 }
150         }
151 }