Merge branch 'master' of ssh://plrg.eecs.uci.edu/home/git/iot2
[iot2.git] / iotjava / iotrmi / Java / IoTSocket.java
1 package iotrmi.Java;
2
3 // Java libraries
4 import java.io.*;
5 import java.net.*;
6 import java.awt.*;
7 import java.util.*;
8 import java.nio.ByteBuffer;
9
10 import java.util.concurrent.Semaphore;
11
12
13 /** Class IoTSocket is the basic class for IoT RMI
14  *  socket communication. This class will be extended
15  *  by both IoTSocketServer and IoTSocketClient
16  *  <p>
17  *  Adapted from Java/C++ socket implementation
18  *  by Keith Vertanen
19  *  @see        <a href="https://www.keithv.com/software/socket/</a>
20  *
21  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
22  * @version     1.0
23  * @since       2016-08-17
24  */
25 public abstract class IoTSocket {
26
27         /**
28          * Class Properties
29          */
30         protected byte data[];
31         protected int localPort;
32         protected int port;
33         protected Socket sock;
34         protected BufferedInputStream input;
35         protected BufferedOutputStream output;
36
37         //protected static Semaphore sendRecvMutex = new Semaphore(1);
38
39         /**
40          * Class Constant
41          */
42         protected static int BUFFSIZE = 128000; // how many bytes our incoming buffer can hold (original)
43         protected static int MSG_LEN_SIZE = 4;  // send length in the size of integer (4 bytes)
44
45         /**
46          * Default constructor
47          */
48         protected IoTSocket(int _port) throws IOException
49         {
50                 localPort = 0;
51                 port = _port;
52                 data = new byte[BUFFSIZE];
53         }
54         
55          
56         protected IoTSocket(int _localPort, int _port) throws IOException
57         {
58                 localPort = _localPort;
59                 port = _port;
60                 data = new byte[BUFFSIZE];
61         }
62
63
64         /**
65          * sendBytes() sends an array of bytes
66          */
67         public synchronized void sendBytes(byte vals[]) throws IOException
68         {
69                 int len = vals.length;
70                 // Write the length first - convert to array of 4 bytes
71                 ByteBuffer bb = ByteBuffer.allocate(MSG_LEN_SIZE);
72                 bb.putInt(len);
73                 output.write(bb.array(), 0, MSG_LEN_SIZE);
74                 output.flush();
75                 // Write the byte array
76                 output.write(vals, 0, len);
77                 output.flush();
78                 receiveAck();
79                 sendAck();
80         }
81
82
83         /**
84          * receiveBytes() receives an array of bytes
85          */
86         public synchronized byte[] receiveBytes(byte val[]) throws IOException
87         {
88                 int i;
89                 int totalbytes = 0;
90                 int numbytes;
91
92                 // Wait until input is available
93                 if (input.available() == 0) {
94                         return null;
95                 }
96
97                 // Read the maxlen first - read 4 bytes here
98                 byte[] lenBytes = new byte[MSG_LEN_SIZE];
99                 input.read(lenBytes, 0, MSG_LEN_SIZE);
100                 int maxlen = ByteBuffer.wrap(lenBytes).getInt();
101                 // Receive until maxlen
102                 if (maxlen>BUFFSIZE) {
103                         System.out.println("IoTSocketClient/Server: Sending more bytes then will fit in buffer! Number of bytes: " + maxlen);
104                         // Allocate a bigger array when needed
105                         int newLen = 2;
106                         while (newLen < maxlen) // Shift until we get a new buffer size that's bigger than maxLen (basically power of 2)
107                                 newLen = newLen << 1;
108                         System.out.println("IoTSocketClient/Server: Allocating a bigger buffer now with size: " + newLen);
109                         BUFFSIZE = newLen;
110                         data = new byte[BUFFSIZE];
111                 }
112                 val = new byte[maxlen];
113                 while (totalbytes < maxlen)
114                 {
115                         numbytes = input.read(data);
116                         // copy the bytes into the result buffer
117                         for (i=totalbytes; i<totalbytes+numbytes; i++)
118                                 val[i] = data[i-totalbytes];
119                         totalbytes += numbytes;
120                 }
121                 // we now send an acknowledgement to the server to let them
122                 // know we've got it
123                 sendAck();
124                 receiveAck();
125
126                 return val;
127         }
128
129
130         /**
131          * Close socket connection
132          */
133         public void close() throws IOException
134         {
135                 sock.close();
136         }
137
138
139         /**
140          * Send ACK
141          */
142         public synchronized void sendAck() throws IOException
143         {
144                 int ack;
145                 ack = 0;
146                 output.write(ack);
147                 output.flush();
148         }
149
150
151         /**
152          * Receive ACK
153          */
154         public synchronized void receiveAck() throws IOException
155         {
156                 int ack;
157                 ack = (int) input.read();
158         }
159
160
161         /**
162          * Set SO TIMEOUT
163          */
164         public void setSoTimeout(int timeout) throws SocketException {
165
166                 sock.setSoTimeout(timeout);
167         }
168 }