f8cffa46a45dc9ab8e758516c4a8c6e6b3cb12fb
[iot2.git] / iotjava / iotrmi / Java / IoTRMICommServer.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 IoTRMICommServer is a class that extends IoTRMI
18  *  <p>
19  *  We will arbitrate packets into 2 queues and wake up the right threads/callers.
20  *  We separate traffics one-directionally.
21  *
22  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
23  * @version     1.0
24  * @since       2017-01-27
25  */
26 public class IoTRMICommServer extends IoTRMIComm {
27
28         /**
29          * Class Properties
30          */
31         private IoTSocketServer rmiServerSend;
32         private IoTSocketServer rmiServerRecv;
33         private AtomicBoolean didServerSendConnect;
34         private AtomicBoolean didServerRecvConnect;
35         
36
37         /**
38          * Constructor (for skeleton)
39          */
40         public IoTRMICommServer(int _portSend, int _portRecv) throws  
41                 ClassNotFoundException, InstantiationException, 
42                         IllegalAccessException, IOException {
43
44                 super();
45                 didServerSendConnect = new AtomicBoolean(false);
46                 didServerRecvConnect = new AtomicBoolean(false);
47                 rmiServerSend = new IoTSocketServer(_portSend);
48                 rmiServerRecv = new IoTSocketServer(_portRecv);
49                 waitForConnectionOnServerSend();
50                 waitForConnectionOnServerRecv();
51                 while(!didServerSendConnect.get());     // Wait until server is connected
52                 while(!didServerRecvConnect.get()); // Wait until server is connected
53                 waitForPacketsOnServer();
54         }
55
56
57         /**
58          * waitForConnectionOnServerRecv() starts a thread that waits server connection
59          */
60         public void waitForConnectionOnServerRecv() {
61
62                 Thread thread = new Thread() {
63                         public void run() {
64                                 try {
65                                         rmiServerRecv.connect();
66                                         didServerRecvConnect.set(true);
67                                 } catch (Exception ex) {
68                                         ex.printStackTrace();
69                                         throw new Error("IoTRMICommServer: Error starting receiver server!");
70                                 }
71                         }
72                 };
73                 thread.start();
74         }
75
76
77         /**
78          * waitForConnectionOnServerSend() starts a thread that waits server connection
79          */
80         public void waitForConnectionOnServerSend() {
81
82                 Thread thread = new Thread() {
83                         public void run() {
84                                 try {
85                                         rmiServerSend.connect();
86                                         didServerSendConnect.set(true);
87                                 } catch (Exception ex) {
88                                         ex.printStackTrace();
89                                         throw new Error("IoTRMICommServer: Error starting sender server!");
90                                 }
91                         }
92                 };
93                 thread.start();
94         }
95
96
97         /**
98          * waitForPacketsOnServer() starts a thread that waits for packet bytes on server side
99          */
100         public void waitForPacketsOnServer() {
101
102                 Thread thread = new Thread() {
103                         public void run() {
104                                 byte[] packetBytes = null;
105                                 while(true) {
106                                         try {
107                                                 packetBytes = rmiServerRecv.receiveBytes(packetBytes);
108                                                 if (packetBytes != null) {
109                                                         //System.out.println("Packet received: " + Arrays.toString(packetBytes));
110                                                         int packetType = IoTRMIComm.getPacketType(packetBytes);
111                                                         if (packetType == IoTRMIUtil.METHOD_TYPE) {
112                                                                 //System.out.println("Method packet: " + Arrays.toString(packetBytes));
113                                                                 methodQueue.offer(packetBytes);
114                                                         } else if (packetType == IoTRMIUtil.RET_VAL_TYPE) {
115                                                                 //System.out.println("Return value packet: " + Arrays.toString(packetBytes));
116                                                                 returnQueue.offer(packetBytes);
117                                                         } else
118                                                                 throw new Error("IoTRMICommServer: Packet type is unknown: " + packetType);
119                                                 } //else
120                                                 //      Thread.sleep(100);
121                                                 packetBytes = null;
122                                         } catch (Exception ex) {
123                                                 ex.printStackTrace();
124                                                 throw new Error("IoTRMICommServer: Error receiving return value bytes on server!");
125                                         }
126                                 }
127                         }
128                 };
129                 thread.start();
130         }
131
132
133         /**
134          * sendReturnObj() for non-struct objects (server side)
135          */
136         public synchronized void sendReturnObj(Object retObj, byte[] methodBytes) {
137
138                 // Send back return value
139                 //byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
140                 byte[] retObjBytes = null;
141                 if (retObj != null)     // Handle nullness
142                         retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
143                 // Send return value together with OBJECT_ID and METHOD_ID for arbitration
144                 int objMethIdLen = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
145                 int headerLen = objMethIdLen + IoTRMIUtil.PACKET_TYPE_LEN;
146                 //byte[] retAllBytes = new byte[headerLen + retObjBytes.length];
147                 byte[] retAllBytes = null;
148                 if (retObj == null)     // Handle nullness
149                         retAllBytes = new byte[headerLen];
150                 else
151                         retAllBytes = new byte[headerLen + retObjBytes.length];
152                 // Copy OBJECT_ID and METHOD_ID
153                 System.arraycopy(methodBytes, 0, retAllBytes, 0, objMethIdLen);
154                 int packetType = IoTRMIUtil.RET_VAL_TYPE;       // This is a return value
155                 byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType);
156                 System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN);
157                 // Copy array of bytes (return object)
158                 if (retObj != null)
159                         System.arraycopy(retObjBytes, 0, retAllBytes, headerLen, retObjBytes.length);
160                 try {
161                         rmiServerSend.sendBytes(retAllBytes);
162                 } catch (IOException ex) {
163                         ex.printStackTrace();
164                         throw new Error("IoTRMICommServer: Error sending bytes in sendReturnObj()!");
165                 }
166         }
167
168
169         /**
170          * sendReturnObj() overloaded to send multiple return objects for structs (server side)
171          */
172         public synchronized void sendReturnObj(Class<?>[] retCls, Object[] retObj, byte[] methodBytes) {
173
174                 // Send back return value
175                 byte[] retObjBytes = returnToBytes(retCls, retObj);
176                 // Send return value together with OBJECT_ID and METHOD_ID for arbitration
177                 int objMethIdLen = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
178                 int headerLen = objMethIdLen + IoTRMIUtil.PACKET_TYPE_LEN;
179                 byte[] retAllBytes = new byte[headerLen + retObjBytes.length];
180                 // Copy OBJECT_ID and METHOD_ID
181                 System.arraycopy(methodBytes, 0, retAllBytes, 0, objMethIdLen);
182                 int packetType = IoTRMIUtil.RET_VAL_TYPE;       // This is a return value
183                 byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType);
184                 System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN);
185                 // Copy array of bytes (return object)
186                 System.arraycopy(retObjBytes, 0, retAllBytes, headerLen, retObjBytes.length);
187                 try {
188                         rmiServerSend.sendBytes(retAllBytes);
189                 } catch (IOException ex) {
190                         ex.printStackTrace();
191                         throw new Error("IoTRMICommServer: Error sending bytes in sendReturnObj()!");
192                 }
193         }
194
195
196         /**
197          * remoteCall() calls a method remotely by passing in parameters (server side)
198          */
199         public synchronized void remoteCall(int objectId, int methodId, Class<?>[] paramCls, Object[] paramObj) {
200
201                 // Send method info
202                 byte[] methodBytes = methodToBytes(objectId, methodId, paramCls, paramObj);
203                 try {
204                         rmiServerSend.sendBytes(methodBytes);
205                 } catch (IOException ex) {
206                         ex.printStackTrace();
207                         throw new Error("IoTRMICommServer: Error when sending bytes in remoteCall()!");
208                 }
209         }
210 }