/*
* Copyright (c) 2006-2007 Graz University of Technology. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The names "Graz University of Technology" and "IAIK of Graz University of
* Technology" must not be used to endorse or promote products derived from
* this software without prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package ejip.jtcpip;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import javax.microedition.io.Datagram;
/**
* Container for a UDP datagram. The DatagamPacket acts as a container for
* incoming and outgoing UDP datagrams. It offers functions to read and write
* data to its buffer and the remote address as truncated connector string (�IP
* address:port�). The buffer that is used has to be provided at the
* instantiation. This allows reuse of a buffer on systems with limited memory
* (or systems without a Garbage Collector).
*
* @author Ulrich Feichter
* @author Tobias Kellner
* @author Christof Rath
* @version $Rev: 994 $ $Date: 2007/01/24 19:37:07 $
*/
public class DatagramPacket implements Datagram
{
/**
* Remote address in the form IPaddress:port[options] where options is a set
* of ;x=y
*/
private String remoteAddr = "";
/** Reference to a byte array */
private byte[] buffer;
/** fixed offset within buffer given at constructor call */
private int initialOffset;
/** the maximum useable space in the buffer given at constructor call */
private int maxLength;
/** pointer for read operations */
private int readPtr;
/** pointer for write operations */
private int writePtr;
/** actual length in the buffer */
private int length;
/**
* Constructs a DatagramPacket for receiving packets of length length. The
* length argument must be less than or equal to buffer.length
*
* @param buffer
* buffer for holding the incoming datagram
* @param length
* the number of bytes to read
*/
public DatagramPacket(byte[] buffer, int length)
{
this(buffer, 0, length);
}
/**
* Constructs a DatagramPacket for receiving packets of length length. The
* length argument must be less than or equal to buffer.length
*
* @param buffer
* buffer for holding the incoming datagram
* @param offset
* the offset for the buffer
* @param length
* the number of bytes to read
*/
public DatagramPacket(byte[] buffer, int offset, int length)
{
if (buffer == null)
throw new NullPointerException();
if (offset < 0 || length < 0 || offset + length > buffer.length)
throw new IndexOutOfBoundsException();
this.buffer = buffer;
initialOffset = offset;
maxLength = offset + length;
reset();
}
/**
* Constructs a datagram packet for sending packets of length length to the
* specified port number on the specified host.
*
* The length argument must be less than or equal to buffer.length
*
* @param buffer
* the packet data
* @param length
* the packet length
* @param remoteAddr
* the destination address ([[protocol:]//]ip_addr:port[;opt=value...])
*/
public DatagramPacket(byte[] buffer, int length, String remoteAddr)
{
this(buffer, 0, length, remoteAddr);
}
/**
* Constructs a datagram packet for sending packets of length length to the
* specified port number on the specified host.
*
* The length argument must be less than or equal to buffer.length
*
* @param buffer
* the packet data
* @param offset
* the packet data offset
* @param length
* the packet length
* @param remoteAddr
* the destination ([//]ip_addr:port[;opt=value...])
*/
public DatagramPacket(byte[] buffer, int offset, int length, String remoteAddr)
{
this(buffer, offset, length);
this.remoteAddr = remoteAddr;
this.length = length; // Set the length of data to send
}
/**
* @see javax.microedition.io.Datagram#getAddress()
*/
public String getAddress()
{
return remoteAddr;
}
/**
* @see javax.microedition.io.Datagram#getData()
*/
synchronized public byte[] getData()
{
byte[] data = new byte[length];
for (int i = 0; i < length; i++)
data[i] = buffer[initialOffset + i];
return data;
}
/**
* @see javax.microedition.io.Datagram#getLength()
*/
public int getLength()
{
return length;
}
/**
* (non-Javadoc)
*
* @see javax.microedition.io.Datagram#getOffset()
*/
public int getOffset()
{
return readPtr;
}
/**
* @see javax.microedition.io.Datagram#reset()
*/
synchronized public void reset()
{
length = 0;
readPtr = initialOffset;
writePtr = initialOffset;
}
/**
* @see javax.microedition.io.Datagram#setAddress(java.lang.String)
*/
public void setAddress(String addr) throws IOException
{
remoteAddr = addr;
}
/**
* @see javax.microedition.io.Datagram#setAddress(javax.microedition.io.Datagram)
*/
public void setAddress(Datagram reference)
{
try
{
if (reference != null)
setAddress(reference.getAddress());
} catch (IOException e)
{
}
}
/**
* @see javax.microedition.io.Datagram#setData(byte[], int, int)
*/
synchronized public void setData(byte[] buffer, int offset, int len)
{
try
{
reset();
write(buffer, offset, len);
} catch (IOException e)
{
throw new IllegalArgumentException(e.getMessage());
}
}
/**
* @see javax.microedition.io.Datagram#setLength(int)
*/
public void setLength(int len)
{
if (len > (maxLength - initialOffset))
throw new IllegalArgumentException();
length = len;
}
/**
* @see java.io.DataInput#readBoolean()
*/
public boolean readBoolean() throws IOException
{
return readByte() != 0;
}
/*
* (non-Javadoc)
*
* @see java.io.DataInput#readByte()
*/
public byte readByte() throws IOException
{
if (readPtr >= (initialOffset + length))
throw new EOFException();
return buffer[readPtr++];
}
/**
* @see java.io.DataInput#readChar()
*/
public char readChar() throws IOException
{
return (char) readByte();
}
/**
* @see java.io.DataInput#readFully(byte[])
*/
synchronized public void readFully(byte[] b) throws IOException
{
readFully(b, 0, length);
}
/**
* @see java.io.DataInput#readFully(byte[], int, int)
*/
public void readFully(byte[] b, int off, int len) throws IOException
{
if (b == null)
throw new NullPointerException();
if (off < 0 || len < 0 || off + len > b.length || len > buffer.length)
throw new IndexOutOfBoundsException();
for (int i = 0; i < len; i++)
{
if (i == length)
throw new EOFException();
b[off + i] = buffer[i];
}
}
/**
* @see java.io.DataInput#readInt()
*/
public int readInt() throws IOException
{
return (readUnsignedShort() << 16) | readUnsignedShort();
}
/**
* @see java.io.DataInput#readLong()
*/
public long readLong() throws IOException
{
return ((long) readInt() & 0xFFFFFFFF << 32) | ((long) readInt() & 0xFFFFFFFF);
}
/**
* @see java.io.DataInput#readShort()
*/
public short readShort() throws IOException
{
return (short) ((readUnsignedByte() << 8) | readUnsignedByte());
}
/**
* @see java.io.DataInput#readUTF()
*/
public String readUTF() throws IOException
{
return DataInputStream.readUTF(this);
}
/**
* @see java.io.DataInput#readUnsignedByte()
*/
public int readUnsignedByte() throws IOException
{
return readByte() & 0xFF;
}
/**
* @see java.io.DataInput#readUnsignedShort()
*/
public int readUnsignedShort() throws IOException
{
return readShort() & 0xFFFF;
}
/**
* @see java.io.DataInput#skipBytes(int)
*/
public int skipBytes(int n) throws IOException
{
//if n < 0 the readPtr must be at least initialOffset
//if n > 0 the readPtr must not be greater than maxLength
int res = Math.max(initialOffset - readPtr, Math.min(n, maxLength - readPtr));
readPtr += res;
return res;
}
/**
* @see java.io.DataOutput#write(int)
*/
synchronized public void write(int b) throws IOException
{
if (writePtr >= maxLength)
throw new IndexOutOfBoundsException();
buffer[writePtr++] = (byte) b;
length++;
}
/**
* @see java.io.DataOutput#write(byte[])
*/
public void write(byte[] b) throws IOException
{
write(b, 0, b.length);
}
/**
* @see java.io.DataOutput#write(byte[], int, int)
*/
synchronized public void write(byte[] b, int off, int len) throws IOException
{
if (b == null)
throw new NullPointerException();
if (off < 0 || len < 0)
throw new IllegalArgumentException();
for (int i = off; i < len; i++)
write(b[i]);
}
/**
* @see java.io.DataOutput#writeBoolean(boolean)
*/
public void writeBoolean(boolean v) throws IOException
{
writeByte(v ? 1 : 0);
}
/**
* @see java.io.DataOutput#writeByte(int)
*/
public void writeByte(int v) throws IOException
{
write(v);
}
/**
* @see java.io.DataOutput#writeChar(int)
*/
public void writeChar(int v) throws IOException
{
writeByte(v);
}
/**
* @see java.io.DataOutput#writeChars(java.lang.String)
*/
public void writeChars(String s) throws IOException
{
write(s.getBytes());
}
/**
* @see java.io.DataOutput#writeInt(int)
*/
public void writeInt(int v) throws IOException
{
writeShort((v >>> 16) & 0xFFFF);
writeShort((v >>> 0) & 0xFFFF);
}
/**
* @see java.io.DataOutput#writeLong(long)
*/
public void writeLong(long v) throws IOException
{
writeInt((int) (v >>> 32));
writeInt((int) (v >>> 0));
}
/**
* @see java.io.DataOutput#writeShort(int)
*/
public void writeShort(int v) throws IOException
{
writeByte((v >>> 8) & 0xFF);
writeByte((v >>> 0) & 0xFF);
}
/**
* @return the buffer
*/
protected byte[] getBuffer()
{
return buffer;
}
public void writeUTF(String value) throws IOException {
// TODO Auto-generated method stub
}
}