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