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/UDPOutputStream.htm 005/* 006 007 Copyright 2007 Creare Inc. 008 009 Licensed under the Apache License, Version 2.0 (the "License"); 010 you may not use this file except in compliance with the License. 011 You may obtain a copy of the License at 012 013 http://www.apache.org/licenses/LICENSE-2.0 014 015 Unless required by applicable law or agreed to in writing, software 016 distributed under the License is distributed on an "AS IS" BASIS, 017 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 See the License for the specific language governing permissions and 019 limitations under the License. 020 */ 021 022/* 023 ***************************************************************** 024 *** *** 025 *** Name : UDPOutputStream *** 026 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 027 *** For : E-Scan *** 028 *** Date : October, 2001 *** 029 *** *** 030 *** Copyright 2001 Creare Inc. *** 031 *** All Rights Reserved *** 032 *** *** 033 *** Description : *** 034 *** This class extends OutputStream, providing its API *** 035 *** for calls to a UDPSocket. *** 036 *** *** 037 *** NB: THIS CLASS IS NOT THREADSAFE. DO NOT SHARE ONE *** 038 *** INSTANCE OF THIS CLASS AMONG MULTIPLE THREADS. *** 039 *** *** 040 ***************************************************************** 041 */ 042 043import java.io.IOException; 044import java.io.OutputStream; 045import java.net.DatagramPacket; 046import java.net.DatagramSocket; 047import java.net.InetAddress; 048import java.net.SocketException; 049import java.net.UnknownHostException; 050 051public class UDPOutputStream extends OutputStream { 052 053 public static final int DEFAULT_BUFFER_SIZE = 1024; 054 public static final int DEFAULT_MAX_BUFFER_SIZE = 8192; 055 056 protected DatagramSocket dsock = null; 057 DatagramPacket dpack = null; 058 InetAddress iAdd = null; 059 int port = 0; 060 061 byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 062 byte[] outdata = null; 063 int idx = 0; // buffer index; points to next empty buffer byte 064 int bufferMax = DEFAULT_MAX_BUFFER_SIZE; 065 066 /* 067 * ******************** constructors ******************* 068 */ 069 /* 070 ***************************************************************** 071 *** *** 072 *** Name : UDPOutputStream *** 073 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 074 *** For : E-Scan *** 075 *** Date : October, 2001 *** 076 *** *** 077 *** Copyright 2001 Creare Inc. *** 078 *** All Rights Reserved *** 079 *** *** 080 *** Description : *** 081 *** Default constructor. *** 082 *** *** 083 ***************************************************************** 084 */ 085 public UDPOutputStream() { 086 } 087 088 /* 089 ***************************************************************** 090 *** *** 091 *** Name : UDPOutputStream *** 092 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 093 *** For : E-Scan *** 094 *** Date : October, 2001 *** 095 *** *** 096 *** Copyright 2001 Creare Inc. *** 097 *** All Rights Reserved *** 098 *** *** 099 *** Description : *** 100 *** Constructor. Sets size of buffer. *** 101 *** *** 102 ***************************************************************** 103 */ 104 public UDPOutputStream(int buffSize) { 105 setBufferSize(buffSize); 106 } 107 108 /* 109 ***************************************************************** 110 *** *** 111 *** Name : UDPOutputStream *** 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 *** Constructor. Sets the address and port of the UDP *** 121 *** socket to write to. *** 122 *** *** 123 ***************************************************************** 124 */ 125 public UDPOutputStream(String address, int portI) 126 throws UnknownHostException, SocketException, IOException { 127 128 open(InetAddress.getByName(address), portI); 129 } 130 131 /* 132 ***************************************************************** 133 *** *** 134 *** Name : UDPOutputStream *** 135 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 136 *** For : E-Scan *** 137 *** Date : November, 2001 *** 138 *** *** 139 *** Copyright 2001 Creare Inc. *** 140 *** All Rights Reserved *** 141 *** *** 142 *** Description : *** 143 *** Constructor. Sets the address and port of the UDP *** 144 *** socket to write to. *** 145 *** *** 146 ***************************************************************** 147 */ 148 public UDPOutputStream(InetAddress address, int portI) 149 throws SocketException, IOException { 150 151 open(address, portI); 152 } 153 154 /* 155 ***************************************************************** 156 *** *** 157 *** Name : UDPOutputStream *** 158 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 159 *** For : E-Scan *** 160 *** Date : October, 2001 *** 161 *** *** 162 *** Copyright 2001 Creare Inc. *** 163 *** All Rights Reserved *** 164 *** *** 165 *** Description : *** 166 *** Constructor. Sets the address and port of the UDP *** 167 *** socket to write to. Sets the size of the buffer. *** 168 *** *** 169 ***************************************************************** 170 */ 171 public UDPOutputStream(String address, int portI, int buffSize) 172 throws UnknownHostException, SocketException, IOException { 173 174 open(InetAddress.getByName(address), portI); 175 setBufferSize(buffSize); 176 } 177 178 /* 179 ***************************************************************** 180 *** *** 181 *** Name : UDPOutputStream *** 182 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 183 *** For : E-Scan *** 184 *** Date : October, 2001 *** 185 *** *** 186 *** Copyright 2001 Creare Inc. *** 187 *** All Rights Reserved *** 188 *** *** 189 *** Description : *** 190 *** Constructor. Sets the address and port of the UDP *** 191 *** socket to write to. Sets the size of the buffer. *** 192 *** *** 193 ***************************************************************** 194 */ 195 public UDPOutputStream(InetAddress address, int portI, int buffSize) 196 throws SocketException, IOException { 197 198 open(address, portI); 199 setBufferSize(buffSize); 200 } 201 202 /* 203 * ********** opening and closing the stream *********** 204 */ 205 /* 206 ***************************************************************** 207 *** *** 208 *** Name : open *** 209 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 210 *** For : E-Scan *** 211 *** Date : October, 2001 *** 212 *** *** 213 *** Copyright 2001 Creare Inc. *** 214 *** All Rights Reserved *** 215 *** *** 216 *** Description : *** 217 *** The user may use this method to set the address and *** 218 *** port of the UDP socket to write to. *** 219 *** *** 220 ***************************************************************** 221 */ 222 public void open(InetAddress address, int portI) 223 throws SocketException, IOException { 224 225 dsock = new DatagramSocket(); 226 iAdd = address; 227 port = portI; 228 } 229 230 /* 231 ***************************************************************** 232 *** *** 233 *** Name : close *** 234 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 235 *** For : E-Scan *** 236 *** Date : October, 2001 *** 237 *** *** 238 *** Copyright 2001 Creare Inc. *** 239 *** All Rights Reserved *** 240 *** *** 241 *** Description : *** 242 *** Close the UDP socket and UDPOutputStream. *** 243 *** *** 244 ***************************************************************** 245 */ 246 @Override 247 public void close() throws IOException { 248 dsock.close(); 249 dsock = null; 250 idx = 0; 251 } 252 253 /* 254 * ********* writing to and flushing the buffer *********** 255 */ 256 /* 257 ***************************************************************** 258 *** *** 259 *** Name : flush *** 260 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 261 *** For : E-Scan *** 262 *** Date : October, 2001 *** 263 *** *** 264 *** Copyright 2001 Creare Inc. *** 265 *** All Rights Reserved *** 266 *** *** 267 *** Description : *** 268 *** Flush current buffer contents to UDP socket. *** 269 *** *** 270 ***************************************************************** 271 */ 272 @Override 273 public void flush() throws IOException { 274 if (idx == 0) { // no data in buffer 275 return; 276 } 277 278 // copy what we have in the buffer so far into a new array; 279 // if buffer is full, use it directly. 280 if (idx == buffer.length) { 281 outdata = buffer; 282 } else { 283 outdata = new byte[idx]; 284 System.arraycopy(buffer, 285 0, 286 outdata, 287 0, 288 idx); 289 } 290 291 // send data 292 dpack = new DatagramPacket(outdata, idx, iAdd, port); 293 dsock.send(dpack); 294 295 // reset buffer index 296 idx = 0; 297 } 298 299 /* 300 ***************************************************************** 301 *** *** 302 *** Name : write(int) *** 303 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 304 *** For : E-Scan *** 305 *** Date : October, 2001 *** 306 *** *** 307 *** Copyright 2001 Creare Inc. *** 308 *** All Rights Reserved *** 309 *** *** 310 *** Description : *** 311 *** Writes the input value to the UDP socket. May *** 312 *** buffer the value. *** 313 *** Input value is converted to a byte. *** 314 *** *** 315 ***************************************************************** 316 */ 317 @Override 318 public void write(int value) throws IOException { 319 buffer[idx] = (byte) (value & 0x0ff); 320 idx++; 321 322 if (idx >= buffer.length) { 323 flush(); 324 } 325 } 326 327 /* 328 ***************************************************************** 329 *** *** 330 *** Name : write(byte[]) *** 331 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 332 *** For : E-Scan *** 333 *** Date : October, 2001 *** 334 *** *** 335 *** Copyright 2001 Creare Inc. *** 336 *** All Rights Reserved *** 337 *** *** 338 *** Description : *** 339 *** Writes the input byte array to the UDP socket. May *** 340 *** buffer the values. *** 341 *** *** 342 ***************************************************************** 343 */ 344 @Override 345 public void write(byte[] data) throws IOException { 346 write(data, 0, data.length); 347 } 348 349 /* 350 ***************************************************************** 351 *** *** 352 *** Name : write(byte[], int, int) *** 353 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 354 *** For : E-Scan *** 355 *** Date : October, 2001 *** 356 *** *** 357 *** Copyright 2001 Creare Inc. *** 358 *** All Rights Reserved *** 359 *** *** 360 *** Description : *** 361 *** Writes len bytes of the input byte array to the UDP *** 362 *** socket, starting at offset off. May buffer the values. *** 363 *** *** 364 ***************************************************************** 365 */ 366 @Override 367 public void write(byte[] data, int off, int len) throws IOException { 368 int lenRemaining = len; 369 370 try { 371 while (buffer.length - idx <= lenRemaining) { 372 System.arraycopy(data, 373 off + (len - lenRemaining), 374 buffer, 375 idx, 376 buffer.length - idx); 377 lenRemaining -= buffer.length - idx; 378 idx = buffer.length; 379 flush(); 380 } 381 382 if (lenRemaining == 0) { 383 return; 384 } 385 386 System.arraycopy(data, 387 off + (len - lenRemaining), 388 buffer, 389 idx, 390 lenRemaining); 391 idx += lenRemaining; 392 } catch (ArrayIndexOutOfBoundsException e) { 393 // 04/03/02 UCB - DEBUG 394 System.err.println("len: " + len); 395 System.err.println("lenRemaining: " + lenRemaining); 396 System.err.println("idx: " + idx); 397 System.err.println("buffer.length: " + buffer.length); 398 System.err.println("offset: " + off); 399 System.err.println("data.length: " + data.length); 400 throw e; 401 } 402 } 403 404 /* 405 * ***************** buffer size accesors ***************** 406 */ 407 /* 408 ***************************************************************** 409 *** *** 410 *** Name : getBufferSize *** 411 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 412 *** For : E-Scan *** 413 *** Date : October, 2001 *** 414 *** *** 415 *** Copyright 2001 Creare Inc. *** 416 *** All Rights Reserved *** 417 *** *** 418 *** Description : *** 419 *** How many bytes are buffered before being flushed. *** 420 *** *** 421 ***************************************************************** 422 */ 423 public int getBufferSize() { 424 return buffer.length; 425 } 426 427 /* 428 ***************************************************************** 429 *** *** 430 *** Name : setMaxBufferSize() *** 431 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 432 *** For : E-Scan *** 433 *** Date : November, 2001 *** 434 *** *** 435 *** Copyright 2001 Creare Inc. *** 436 *** All Rights Reserved *** 437 *** *** 438 *** Description : *** 439 *** Allows user to set upper limit on output buffer *** 440 *** size. Set by default to DEFAULT_MAX_BUFFER_SIZE. *** 441 *** *** 442 ***************************************************************** 443 */ 444 public void setMaxBufferSize(int max) { 445 bufferMax = max; 446 } 447 448 /* 449 ***************************************************************** 450 *** *** 451 *** Name : setBufferSize() *** 452 *** By : U. Bergstrom (Creare Inc., Hanover, NH) *** 453 *** For : E-Scan *** 454 *** Date : October, 2001 *** 455 *** *** 456 *** Copyright 2001 Creare Inc. *** 457 *** All Rights Reserved *** 458 *** *** 459 *** Description : *** 460 *** Sets the length of the buffer. Must be at least 1 *** 461 *** byte long. Tries to flush any data currently in buffer *** 462 *** before resetting the size. *** 463 *** *** 464 ***************************************************************** 465 */ 466 public void setBufferSize(int buffSize) { 467 try { 468 flush(); 469 } catch (IOException ioe) { 470 } 471 472 if (buffSize == buffer.length) { 473 // a no-op; we are already the right size 474 return; 475 } else if (buffSize > 0) { 476 if (buffSize > bufferMax) { 477 buffer = new byte[bufferMax]; 478 } else { 479 buffer = new byte[buffSize]; 480 } 481 } else { 482 buffer = new byte[1]; 483 } 484 } 485}