001package jmri.util.com.rbnb;
002
003// This class comes from the Java2s code examples at
004// http://www.java2s.com/Code/Java/Network-Protocol/UDPInputStream.htm
005/*
006 Copyright 2007 Creare Inc.
007
008 Licensed under the Apache License, Version 2.0 (the "License"); 
009 you may not use this file except in compliance with the License. 
010 You may obtain a copy of the License at 
011
012 http://www.apache.org/licenses/LICENSE-2.0 
013
014 Unless required by applicable law or agreed to in writing, software 
015 distributed under the License is distributed on an "AS IS" BASIS, 
016 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
017 See the License for the specific language governing permissions and 
018 limitations under the License.
019 */
020
021/*
022 *****************************************************************
023 ***                ***
024 ***  Name :  UDPInputStream                                 ***
025 ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
026 ***  For  :  E-Scan            ***
027 ***  Date :  October, 2001          ***
028 ***                ***
029 ***  Copyright 2001 Creare Inc.        ***
030 ***  All Rights Reserved          ***
031 ***                ***
032 ***  Description :            ***
033 ***       This class extends InputStream, providing its API   ***
034 ***   for calls to a UDPSocket.                               ***
035 ***                ***
036 *****************************************************************
037 */
038
039import java.io.IOException;
040import java.io.InputStream;
041import java.net.DatagramPacket;
042import java.net.DatagramSocket;
043import java.net.InetAddress;
044import java.net.SocketException;
045import java.net.UnknownHostException;
046
047public class UDPInputStream extends InputStream {
048
049    private static final int PACKET_BUFFER_SIZE = 5000;
050
051    DatagramSocket dsock = null;
052    DatagramPacket dpack = null;
053
054    byte[] ddata = new byte[PACKET_BUFFER_SIZE];
055    int packSize = 0;
056    int packIdx = 0;
057
058    int value;
059
060    /*
061     * ******************** constructors *******************
062     */
063    /*
064     *****************************************************************
065     ***                ***
066     ***  Name :  UDPInputStream                                 ***
067     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
068     ***  For  :  E-Scan            ***
069     ***  Date :  October, 2001          ***
070     ***                ***
071     ***  Copyright 2001 Creare Inc.        ***
072     ***  All Rights Reserved          ***
073     ***                ***
074     ***  Description :            ***
075     ***       Default constructor.                                ***
076     ***                ***
077     *****************************************************************
078     */
079    public UDPInputStream() {
080    }
081
082    /*
083     *****************************************************************
084     ***                ***
085     ***  Name :  UDPInputStream                                 ***
086     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
087     ***  For  :  E-Scan            ***
088     ***  Date :  October, 2001          ***
089     ***                ***
090     ***  Copyright 2001 Creare Inc.        ***
091     ***  All Rights Reserved          ***
092     ***                ***
093     ***  Description :            ***
094     ***       Constructor.  Requires the address and port of the  ***
095     ***   UDP socket to read from.                                ***
096     ***                ***
097     *****************************************************************
098     */
099    public UDPInputStream(String address, int port)
100            throws UnknownHostException, SocketException {
101
102        open(address, port);
103    }
104
105    /*
106     * ********** opening and closing the stream ***********
107     */
108    /*
109     *****************************************************************
110     ***                ***
111     ***  Name :  open                                             ***
112     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
113     ***  For  :  E-Scan            ***
114     ***  Date :  October, 2001          ***
115     ***                ***
116     ***  Copyright 2001 Creare Inc.        ***
117     ***  All Rights Reserved          ***
118     ***                ***
119     ***  Description :            ***
120     ***       The user may use this method to set the address and ***
121     ***   port of the UDP socket to read from.                    ***
122     ***                ***
123     *****************************************************************
124     */
125    public void open(String address, int port) throws UnknownHostException, SocketException {
126        // Changed to allow a datagram to be received on the broadcast address.
127        if (address != null) {
128            dsock = new DatagramSocket(port, InetAddress.getByName(address));
129        } else {
130            dsock = new DatagramSocket(port);
131        }
132    }
133
134
135    /*
136     *****************************************************************
137     ***                ***
138     ***  Name :  close                                       ***
139     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
140     ***  For  :  E-Scan            ***
141     ***  Date :  October, 2001          ***
142     ***                ***
143     ***  Copyright 2001 Creare Inc.        ***
144     ***  All Rights Reserved          ***
145     ***                ***
146     ***  Description :            ***
147     ***       Close the UDP socket and UDPInputStream.            ***
148     ***                ***
149     *****************************************************************
150     */
151    @Override
152    public void close() throws IOException {
153        dsock.close();
154        dsock = null;
155        ddata = null;
156        packSize = 0;
157        packIdx = 0;
158    }
159
160    /*
161     * **** reading, skipping and checking available data *****
162     */
163    /*
164     *****************************************************************
165     ***                ***
166     ***  Name :  available                                 ***
167     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
168     ***  For  :  E-Scan            ***
169     ***  Date :  October, 2001          ***
170     ***                ***
171     ***  Copyright 2001 Creare Inc.        ***
172     ***  All Rights Reserved          ***
173     ***                ***
174     ***  Description :            ***
175     ***       Determines how many more values may be read before  ***
176     ***   next blocking read.                                     ***
177     ***                ***
178     *****************************************************************
179     */
180    @Override
181    public int available() throws IOException {
182        return packSize - packIdx;
183    }
184
185    /*
186     *****************************************************************
187     ***                ***
188     ***  Name :  read()                                     ***
189     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
190     ***  For  :  E-Scan            ***
191     ***  Date :  October, 2001          ***
192     ***                ***
193     ***  Copyright 2001 Creare Inc.        ***
194     ***  All Rights Reserved          ***
195     ***                ***
196     ***  Description :            ***
197     ***       Reads the next value available.  Returns the value  ***
198     ***   as an integer from 0 to 255.                            ***
199     ***                ***
200     *****************************************************************
201     */
202    @Override
203    public int read() throws IOException {
204        if (packIdx == packSize) {
205            receive();
206        }
207
208        value = ddata[packIdx] & 0xff;
209        packIdx++;
210        return value;
211    }
212
213    /*
214     *****************************************************************
215     ***                ***
216     ***  Name :  read(byte[])                                 ***
217     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
218     ***  For  :  E-Scan            ***
219     ***  Date :  October, 2001          ***
220     ***                ***
221     ***  Copyright 2001 Creare Inc.        ***
222     ***  All Rights Reserved          ***
223     ***                ***
224     ***  Description :            ***
225     ***       Reads the next buff.length values into the input    ***
226     ***   byte array, buff.                                       ***
227     ***                ***
228     *****************************************************************
229     */
230    @Override
231    public int read(byte[] buff) throws IOException {
232        return read(buff, 0, buff.length);
233    }
234
235    /*
236     *****************************************************************
237     ***                ***
238     ***  Name :  read(byte[], int, int)                         ***
239     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
240     ***  For  :  E-Scan            ***
241     ***  Date :  October, 2001          ***
242     ***                ***
243     ***  Copyright 2001 Creare Inc.        ***
244     ***  All Rights Reserved          ***
245     ***                ***
246     ***  Description :            ***
247     ***       Reads the next len values into the input byte array,***
248     ***   buff, starting at offset off.                           ***
249     ***                ***
250     *****************************************************************
251     */
252    @Override
253    public int read(byte[] buff, int off, int len) throws IOException {
254        if (packIdx == packSize) {
255            receive();
256        }
257
258        int lenRemaining = len;
259
260        while (available() < lenRemaining) {
261            System.arraycopy(ddata,
262                    packIdx,
263                    buff,
264                    off + (len - lenRemaining),
265                    available());
266            lenRemaining -= available();
267            receive();
268        }
269
270        System.arraycopy(ddata,
271                packIdx,
272                buff,
273                off + (len - lenRemaining),
274                lenRemaining);
275        packIdx += lenRemaining;
276        return len;
277    }
278
279    /*
280     *****************************************************************
281     ***                ***
282     ***  Name :  skip                                       ***
283     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
284     ***  For  :  E-Scan            ***
285     ***  Date :  October, 2001          ***
286     ***                ***
287     ***  Copyright 2001 Creare Inc.        ***
288     ***  All Rights Reserved          ***
289     ***                ***
290     ***  Description :            ***
291     ***       Skips over the next len values.                     ***
292     ***                ***
293     *****************************************************************
294     */
295    @Override
296    public long skip(long len) throws IOException {
297        if (packIdx == packSize) {
298            receive();
299        }
300
301        long lenRemaining = len;
302
303        while (available() < lenRemaining) {
304            lenRemaining -= available();
305            receive();
306        }
307
308        packIdx += (int) lenRemaining;
309        return len;
310    }
311
312    /*
313     * **************** receiving more data *****************
314     */
315    /*
316     *****************************************************************
317     ***                ***
318     ***  Name :  receive                                    ***
319     ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
320     ***  For  :  E-Scan            ***
321     ***  Date :  October, 2001          ***
322     ***                ***
323     ***  Copyright 2001 Creare Inc.        ***
324     ***  All Rights Reserved          ***
325     ***                ***
326     ***  Description :            ***
327     ***       A blocking read to receive more data from the UDP   ***
328     ***   socket.                                                 ***
329     ***                ***
330     *****************************************************************
331     */
332    private void receive() throws IOException {
333        dpack = new DatagramPacket(ddata, PACKET_BUFFER_SIZE);
334        dsock.receive(dpack);
335        packIdx = 0;
336        packSize = dpack.getLength();
337    }
338
339    /*
340     * ******* marking and reseting are unsupported *******
341     */
342    @Override
343    public void mark(int readlimit) {
344    }
345
346    @Override
347    public void reset() throws IOException {
348        throw new IOException("Marks are not supported by UDPInputStream.");
349    }
350
351    @Override
352    public boolean markSupported() {
353        return false;
354    }
355
356}