|
Message
From: cvs at opencores.org<cvs@o...>
Date: Wed Jan 24 20:37:07 CET 2007
Subject: [cvs-checkins] MODIFIED: jop ...
Date: 00/07/01 24:20:37 Added: jop/java/target/src/common/ejip/jtcpip Bitmap.java DatagramPacket.java DatagramSocket.java DHCPClient.java ICMP.java ICMPPacket.java IP.java IPPacket.java JtcpipException.java NwLoopRtThread.java NwLoopThread.java Payload.java Socket.java StackParameters.java TCP.java TCPConnection.java TCPInputStream.java TCPOutputStream.java TCPPacket.java TestInputStream.java TestOutputStream.java UDP.java UDPConnection.java UDPPacket.java Util.java Log: move from ejip2 to ejip Revision Changes Path 1.1 jop/java/target/src/common/ejip/jtcpip/Bitmap.java http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/Bitmap.java?rev=1.1&content-type=text/x-cvsweb-markup Index: Bitmap.java =================================================================== /* * 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 ejip.jtcpip.util.Util; /** * Class to handle Bitmaps * * @author Ulrich Feichter * @author Tobias Kellner * @author Christof Rath * @version $Rev: 860 $ $Date: 2007/01/24 19:37:07 $ */ public class Bitmap { /** Size of the bitmap in bits */ int size; /** Bit pool */ byte[] bitmap; /** * Initalizes the bitmap. * * @param size * Desired number of bits in the bitmap */ public Bitmap(int size) { this.size = size; bitmap = new byte[Util.divRoundUp(size, 8)]; // if the size doesn't fall onto a byte boundary add another byte } /** * Clears the complete bitmap. */ public void clearBitmap() { for (int i = 0; i < bitmap.length; i++) bitmap[i] = 0; } /** * Sets a single bit in the bitmap. * * @param pos * Position of the bit to set */ public void setBit(int pos)
{
if (pos < size)
bitmap[pos / 8] |= (byte) (1 << (pos % 8));
}
/**
* Clears a single bit in the bitmap
*
* @param pos
*/
public void clearBit(int pos)
{
if (pos < size)
bitmap[pos / 8] &= ~(byte) (1 << (pos % 8));
}
/**
* Sets multiple bits. Set <code>count</code> bits, starting at
* <code>pos</code>.
*
* @param pos
* Position of the first bit to set
* @param count
* Number of bits to set
*/
public void setBits(int pos, int count)
{
if (pos >= size)
return;
if ((pos + count) >= size)
count = (size - pos);
if (pos % 8 > 0) // pos doesn'f fall on a byte boundary
{
// => handle the first bits bit per bit
int i;
for (i = pos; i < (pos + Math.min(8 - (pos % 8), count)); i++)
setBit(i);
count -= (i - pos);
pos = i;
}
if (count == 0)
return;
if (count % 8 > 0) // the last bits do not fall on a byte boundary
{
// => handle the last bits bit per bit
for (int i = (pos + count - (count % 8)); i < (pos + count); i++)
setBit(i);
count -= (pos + count) % 8;
}
if (count == 0)
return;
for (int i = (pos / 8); i < (pos / 8) + (count / 8); i++)
// handle the rest (whole bytes in the middle)
bitmap[i] = (byte) 0xFF;
}
/**
* Clears multiple bits. Clear <code>count</code> bits, starting at
* <code>pos</code>.
*
* @param pos
* Position of the first bit to clear
* @param count
* Number of bits to clear
*/
public void clearBits(int pos, int count)
{
if (pos >= size)
return;
if ((pos + count) >= size)
count = (size - pos);
if (pos % 8 > 0) // pos doesn'f fall on a byte boundary
{
// => handle the first bits bit per bit
int i;
for (i = pos; i < (pos + Math.min(8 - (pos % 8), count)); i++)
clearBit(i);
count -= (i - pos);
pos = i;
}
if (count == 0)
return;
if (count % 8 > 0) // the last bits do not fall on a byte boundary
{
// => handle the last bits bit per bit
for (int i = (pos + count - (count % 8)); i < (pos + count); i++)
clearBit(i);
count -= (pos + count) % 8;
}
if (count == 0)
return;
for (int i = (pos / 8); i < (pos / 8) + (count / 8); i++)
// handle the rest (whole bytes in the middle)
bitmap[i] = 0;
}
/**
* Check whether a bit at a given position is set.
*
* @param pos
* Position of the bit to check
* @return Whether the bit is set
*/
public boolean isSet(int pos)
{
if (pos >= size)
return false;
int i = (byte) (1 << (pos % 8)) & bitmap[pos / 8];
return i != 0;
}
/**
* Tests if all bits of the bitmap are set.
*
* @return True if all bits are set
*/
public boolean allSet()
{
if (size % 8 > 0) // the last byte is not filled by the bitmap
{
// Set all bits that exceed the bitmap to 1
int i = 0xFF << (size % 8);
bitmap[bitmap.length - 1] |= i;
}
for (int i = 0; i < bitmap.length; i++)
if (bitmap[i] != (byte) 0xFF)
return false;
return true;
}
/**
* Tests if all bits of the bitmap until a certain position are set.
*
* @param until
* Number of bits to check from the start
* @return True if all bits until <code>until</code> are set
*/
public boolean allSet(int until)
{
if (until >= size)
return allSet();
for (int i = 0; i < until / 8; i++)
if (bitmap[i] != (byte) 0xFF)
return false;
if (until % 8 > 0) // the last byte is not filled by the bitmap
{
// Set all bits that ecxeed the bitmap to 1
byte b = bitmap[until / 8];
int m = 0xFF << (until % 8);
b |= m;
if (b != (byte) 0xFF)
return false;
}
return true;
}
/**
* Returns a string that shows every bit in the given byte.
*
* @param b
* The byte
* @return string representation of a byte
*/
public String byteToBitString(byte b)
{
String res = "|";
for (byte j = 0; j < 8; j++)
res += ((b >> j) & (byte) 1) == 1 ? "1|" : "0|";
return res;
}
/**
* Prints the content of the bitmap to {@link System#out}.
*/
public void print()
{
System.out.println("+---------------+");
for (int i = 0; i < bitmap.length; i++)
if ((i == bitmap.length - 1) && (size % 8 > 0))
{
char[] s = byteToBitString(bitmap[i]).toCharArray();
for (byte b = (byte) (size % 8); b < 8; b++)
s[b * 2 + 1] = 'x';
System.out.println(s);
}
else
System.out.println(byteToBitString(bitmap[i]));
System.out.println("+---------------+");
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/DatagramPacket.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/DatagramPacket.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: DatagramPacket.java
===================================================================
/*
* 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
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/DatagramSocket.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/DatagramSocket.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: DatagramSocket.java
===================================================================
/*
* 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.IOException;
import javax.microedition.io.Connection;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import com.sun.cldc.io.ConnectionBaseInterface;
import ejip.jtcpip.util.StringFunctions;
/**
* Application interface to the UDP layer. The DatagramSocket holds a reference
* to a corresponding UDPConnection, provides some functions to create new
* Datagrams and the functions to send and receive them.
*
* @author Ulrich Feichter
* @author Tobias Kellner
* @author Christof Rath
* @version $Rev: 994 $ $Date: 2007/01/24 19:37:07 $
*/
public class DatagramSocket implements DatagramConnection, ConnectionBaseInterface
{
/** Reference to the UDPConnection */
private UDPConnection conn;
/** Default remote host */
private String defaultRemoteHost;
/**
* Dummy constructor - see {@link Connector#open(String)}.
*
* @param addr
* Format: [[protocol:]//][ip address]:port[;opt1=val1...]
* @throws IOException
* @see #openPrim(String, int, boolean)
*/
public DatagramSocket(String addr) throws IOException
{
openPrim(addr, 0, false);
}
/**
* @see javax.microedition.io.DatagramConnection#getMaximumLength()
*/
public int getMaximumLength() throws IOException
{
return StackParameters.UDP_DATA_SIZE;
}
/**
* @see javax.microedition.io.DatagramConnection#getNominalLength()
*/
public int getNominalLength() throws IOException
{
return getMaximumLength();
}
/**
* @see javax.microedition.io.DatagramConnection#newDatagram(int)
*/
public Datagram newDatagram(int size) throws IOException
{
return newDatagram(size, defaultRemoteHost);
}
/**
* @see javax.microedition.io.DatagramConnection#newDatagram(int,
* java.lang.String)
*/
public Datagram newDatagram(int size, String addr) throws IOException
{
if (size < 0 || size > getMaximumLength())
throw new IllegalArgumentException();
byte[] b = new byte[size];
return newDatagram(b, size, addr);
}
/**
* @see javax.microedition.io.DatagramConnection#newDatagram(byte[], int)
*/
public Datagram newDatagram(byte[] buf, int size) throws IOException
{
return new DatagramPacket(buf, size, defaultRemoteHost);
}
/**
* @see javax.microedition.io.DatagramConnection#newDatagram(byte[], int,
* java.lang.String)
*/
public Datagram newDatagram(byte[] buf, int size, String addr) throws IOException
{
if (size < 0 || size > getMaximumLength())
throw new IllegalArgumentException();
Datagram dg = new DatagramPacket(buf, size);
if (addr != null)
dg.setAddress(addr);
return dg;
}
/**
* @see javax.microedition.io.DatagramConnection#receive(javax.microedition.io.Datagram)
*/
public void receive(Datagram dgram) throws IOException
{
if (conn != null)
conn.receive(dgram);
}
/**
* @see javax.microedition.io.DatagramConnection#send(javax.microedition.io.Datagram)
*/
public void send(Datagram dgram) throws IOException
{
if (conn != null)
conn.send(dgram);
}
/**
* @see javax.microedition.io.Connection#close()
*/
public void close() throws IOException
{
if (conn != null)
{
conn.close();
conn = null;
}
}
/**
* Opens the datagram socket.
*
* <pre>
* URL format:
* [//][host]:port[;option1=value1[;option2=value2[...]]]
* </pre>
*
* If the host is given a connection will be established to the given
* host:port the local port will be random. Else a listening connection will
* be opened on the given port
*
* <p>
* Examples: (Note that 'datagram:' will be removed by
* {@link Connector#open(String)})
* <p>
* A datagram connection for accepting datagrams<br>
* datagram://:1234
* <p>
* A datagram connection for sending to a server:<br>
* datagram://123.456.789.12:1234
* <p>
*
* <b>Note: </b> Even in "client mode" is the actual destination always set
* in the DatagramPacket! The given remote address is used as default
* destination.
*
* <p>
* Note that the port number in "server mode" (unspecified host name) is
* that of the receiving port. The port number in "client mode" (host name
* specified) is that of the target port. The reply-to port in both cases is
* never unspecified. In "server mode", the same port number is used for
* both receiving and sending. In "client mode", the reply-to port is always
* dynamically allocated.
*
* @param name
* The URL for the connection
* @param mode
* The access mode
* @param timeouts
* A flag to indicate that the caller wants timeout exceptions
* @return A new Connection object
*/
public Connection openPrim(String name, int mode, boolean timeouts) throws IOException
{
int addr = StringFunctions.getAddrFromConnectorStr(name);
int port;
if (addr == 0)
port = StringFunctions.getPortFromConnectorStr(name);
else
{
port = UDPConnection.newLocalPort();
defaultRemoteHost = name;
}
conn = UDPConnection.newConnection(port);
if (conn == null)
throw new JtcpipException("No connection available!");
return this;
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/DHCPClient.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/DHCPClient.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: DHCPClient.java
===================================================================
/*
* 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.IOException;
import javax.microedition.io.Datagram;
import ejip.CS8900;
import ejip.Net;
import ejip.jtcpip.util.Debug;
import ejip.jtcpip.util.NumFunctions;
/**
* Implements a basic DHCP client
*
* @author Ulrich Feichter
* @author Tobias Kellner
* @author Christof Rath
* @version $Rev: 975 $ $Date: 2007/01/24 19:37:07 $
*/
public class DHCPClient
{
/**
* UDP connection to the DHCP server to the server port 67 from the server
* port 68
*/
private static UDPConnection conn;
/** buffer for the datagram */
private static byte[] buffer;
/** datagram for the communication */
private static Datagram dg;
/** transaction id */
private static int transID;
/** Timeout when we have to renew the lease */
private static long renewalTimeout;
/** IP address lease time */
private static int leaseTimeSec;
/** Server identifier (ip address) */
private static int serverID;
/** Time when we got the lease (required for the lease timeout) */
private static long ackTime;
/** time in seconds between two trys */
public static int retryTimeout = 15;
public static void init(){
buffer = new byte[StackParameters.UDP_DATA_SIZE];
conn = UDPConnection.newConnection(68, 0xFFFFFFFF, 67);
dg = new DatagramPacket(buffer, buffer.length, "//255.255.255.255:67");
}
/**
* forbids instantiation
*/
private DHCPClient()
{
}
/**
* Creates a new transaction ID and resets the datagram
*/
private static void start()
{
transID = NumFunctions.rand.nextInt();
renewalTimeout = 0;
leaseTimeSec = 0;
serverID = 0;
ackTime = 0;
Net.linkLayer.gateway = 0;
Net.linkLayer.netmask = 0;
}
/**
* Sends a DHCP discover datagram.
*
* @return the datagram with the DHCP server answer
* @throws IOException
*/
private static Datagram discover() throws IOException
{
dg.reset();
dg.write(1); // OP: request
dg.write(1); // hw_type: ethernet
dg.write(6); // hw_addr_len: 6 for ethernet
dg.write(0); // hops
dg.writeInt(transID); // transaction ID
dg.writeShort(0); // secs: time elapsed since start of DHCP request
dg.writeShort(0); // flags: MSB set rest must be zero
dg.writeInt(0); // client ip address
dg.writeInt(0); // your (client) ip address
dg.writeInt(0); // server ip address
dg.writeInt(0); // relay agent ip address
dg.write(CS8900.eth[0]); // client hardware address
dg.write(CS8900.eth[1]); // s.a.a.
dg.write(CS8900.eth[2]); // s.a.a.
dg.write(CS8900.eth[3]); // s.a.a.
dg.write(CS8900.eth[4]); // s.a.a.
dg.write(CS8900.eth[5]); // s.a.a.
dg.writeShort(0); // s.a.a.
dg.writeInt(0); // s.a.a.
dg.writeInt(0); // s.a.a.
dg.writeLong(0); // server host name
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0); // boot file name
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
// Options (1 byte option type, 1 byte option length in bytes, n bytes
// option value)
dg.writeInt(0x63825363); // Magic cookie
dg.write(53); // DHCP Msg type
dg.write(1); // only one byte of data
dg.write(1); // DHCP discover
dg.write(61); // Client identifier
dg.write(7); // 7 bytes of data
dg.write(1); // 1 for Ethernet addr
dg.write(CS8900.eth[0]); // client hardware address
dg.write(CS8900.eth[1]); // s.a.a.
dg.write(CS8900.eth[2]); // s.a.a.
dg.write(CS8900.eth[3]); // s.a.a.
dg.write(CS8900.eth[4]); // s.a.a.
dg.write(CS8900.eth[5]); // s.a.a.
dg.write(12); // Host name
dg.write(6); // 6 bytes of data
dg.writeChar('j'); // jcpip
dg.writeChar('t');
dg.writeChar('c');
dg.writeChar('p');
dg.writeChar('i');
dg.writeChar('p');
dg.write(55); // Parameter Request List
dg.write(2); // 2 bytes of data
dg.write(1); // Subnetmask
dg.write(3); // Gateway
dg.write(0xFF); // End of Options
conn.send(dg);
conn.receive(dg);
if (dg.getLength() != 0)
{
dg.skipBytes(28); //jump to chaddr (client hardware address)
//and check if the received datagram is for our MAC address
boolean isOurs = true;
for (int i = 0; i < 6; i++)
if (dg.readUnsignedByte() != CS8900.eth[i])
{
isOurs = false;
break;
}
if (!isOurs)
dg.reset();
else dg.skipBytes(-34);
}
return dg;
}
/**
* Sends a DHCP request for a given IP address
*
* @param ipAddr
* @return DHCP server answer
* @throws IOException
*/
private static Datagram request(int ipAddr) throws IOException
{
dg.reset();
dg.write(1); // OP: request
dg.write(1); // hw_type: ethernet
dg.write(6); // hw_addr_len: 6 for ethernet
dg.write(0); // hops
dg.writeInt(transID); // transaction ID
dg.writeShort(0); // secs: time elapsed since start of DHCP request
// but must be the same as at discover!!!!
dg.writeShort(0x0000); // flags: MSB = uni/broadcast; rest must be zero
dg.writeInt(ipAddr); // client ip address
dg.writeInt(0); // your (client) ip address
dg.writeInt(0); // server ip address
dg.writeInt(0); // relay agent ip address
dg.write(CS8900.eth[0]); // client hardware address
dg.write(CS8900.eth[1]); // s.a.a.
dg.write(CS8900.eth[2]); // s.a.a.
dg.write(CS8900.eth[3]); // s.a.a.
dg.write(CS8900.eth[4]); // s.a.a.
dg.write(CS8900.eth[5]); // s.a.a.
dg.writeShort(0); // s.a.a.
dg.writeInt(0); // s.a.a.
dg.writeInt(0); // s.a.a.
dg.writeLong(0); // server host name
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0); // boot file name
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
dg.writeLong(0);
// Options (1 byte option type, 1 byte option length in bytes, n bytes
// option value)
dg.writeInt(0x63825363); // Magic cookie
dg.write(53); // DHCP Msg type
dg.write(1); // only one byte of data
dg.write(3); // DHCP request
dg.write(61); // Client identifier
dg.write(7); // 7 bytes of data
dg.write(1); // 1 for Ethernet addr
dg.write(CS8900.eth[0]); // client hardware address
dg.write(CS8900.eth[1]); // s.a.a.
dg.write(CS8900.eth[2]); // s.a.a.
dg.write(CS8900.eth[3]); // s.a.a.
dg.write(CS8900.eth[4]); // s.a.a.
dg.write(CS8900.eth[5]); // s.a.a.
dg.write(12); // Host name
dg.write(6); // 6 bytes of data
dg.writeChar('j'); // jcpip
dg.writeChar('t');
dg.writeChar('c');
dg.writeChar('p');
dg.writeChar('i');
dg.writeChar('p');
dg.write(55); // Parameter Request List
dg.write(3); // 2 bytes of data
dg.write(1); // Subnetmask
dg.write(3); // Gateway
dg.write(51); // Lease time
dg.write(0xFF); // End of Options
conn.send(dg);
conn.receive(dg);
if (dg.getLength() != 0)
{
dg.skipBytes(28); //jump to chaddr (client hardware address)
//and check if the received datagram is for our MAC address
boolean isOurs = true;
for (int i = 0; i < 6; i++)
if (dg.readUnsignedByte() != CS8900.eth[i])
{
isOurs = false;
break;
}
if (!isOurs)
dg.reset();
else dg.skipBytes(-34);
}
return dg;
}
/**
* Sets the IP address, the Subnet mask and the Gateway
*
* @return true if the DHCP ACK has been received
*/
public static boolean setNetParams()
{
try
{
int offeredIP = 0;
start();
discover();
if (dg.getLength() == 0)
{
return false;
}
dg.setAddress("//255.255.255.255:67"); // send again a broadcast
dg.skipBytes(16); // jump to yiaddr
offeredIP = dg.readInt();
dg.skipBytes(8); // jump to chaddr (client MAC)
request(offeredIP);
if (dg.getLength() == 0)
{
return false;
}
return processOptions();
} catch (IOException e)
{
e.printStackTrace();
return false;
}
}
/**
* Checks if the renewalTimeout has been reached and send a DHCP request in
* case
*
* @return true if everything went right
*/
public static boolean renewIfNecessary()
{
if (renewalTimeout > System.currentTimeMillis())
return true;
try
{
start();
request(Net.linkLayer.ip);
if (dg.getLength() == 0)
{
return false;
}
return processOptions();
} catch (IOException e)
{
e.printStackTrace();
return false;
}
}
/**
* @return true if the processed datagram was a DHCP ACK packet
* @throws IOException
*/
private static boolean processOptions() throws IOException
{
int offeredIP;
dg.skipBytes(16); // jump to yiaddr
offeredIP = dg.readInt(); // read yiaddr
Net.linkLayer.ip = offeredIP;
dg.skipBytes(220); // jump to options (after magic cookie)
int opt; // DHCP option
int cnt; // count of option value bytes
int value = 0; // option value;
boolean result = false;
while ((opt = dg.readUnsignedByte()) != 0xFF)
{
cnt = dg.readUnsignedByte();
switch (cnt)
{
case 1:
value = dg.readUnsignedByte();
break;
case 2:
value = dg.readUnsignedShort();
break;
case 4:
value = dg.readInt();
break;
default:
for (int i = 0; i < cnt; i++)
dg.readByte();
}
// if (Debug.enabled)
// Debug.println("DHCP opt: " + opt + " cnt: " + cnt + " val: " + value, Debug.DBG_OTHER);
if (Debug.enabled)
Debug.println("DHCP opt", Debug.DBG_OTHER);
// interpret the options
switch (opt)
{
case 53: // DHCP Msg type
result = (value == 5); // 5: DHCP ACK
if (result)
ackTime = System.currentTimeMillis();
break;
case 58: // renewal time
renewalTimeout = value;
break;
case 51: // address lease time
leaseTimeSec = value;
break;
case 54: // server identifier
serverID = value;
break;
case 1: // subnet mask
Net.linkLayer.netmask = value;
break;
case 3: // gateway
Net.linkLayer.gateway = value;
break;
}
}
if (renewalTimeout > 0) // there has been a 'renewal time'-option
renewalTimeout = ackTime + renewalTimeout * 1000; // as the
// ackTime is in
// seconds
else if (leaseTimeSec > 0) // at least there has been an 'address lease
// time'-option
renewalTimeout = ackTime + leaseTimeSec * 500; // according to RFC
// if not given by
// the server it
// should be 0.5 of
// the leas time
else
renewalTimeout = ackTime + 3600000; // send renewal every hour
return result;
}
/**
* @return the address lease time in hours
*/
public static int getLeaseTime()
{
return leaseTimeSec / 3600;
}
/**
* @return the renewal time in hours
*/
public static int getRenewalTime()
{
return (int) (renewalTimeout - ackTime) / 3600000;
}
/**
* @return the server IP address
*/
public static int getServerIP()
{
return serverID;
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/ICMP.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/ICMP.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: ICMP.java
===================================================================
/*
* 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 ejip.jtcpip.util.Debug;
/**
* Class to handle ICMP packets.
*
* @author Ulrich Feichter
* @author Tobias Kellner
* @author Christof Rath
* @version $Rev: 984 $ $Date: 2007/01/24 19:37:07 $
*/
class ICMP
{
/** 0 */
protected final static byte TYPE_ECHO_REPLY = 0;
/** 3: Destination unreachable */
protected final static byte TYPE_DEST_UNREACH = 3;
/** 4: Source quench */
protected final static byte TYPE_SRC_QUENCH = 4;
/** 8 */
protected final static byte TYPE_ECHO = 8;
/** 11: Time exceeded */
protected final static byte TYPE_TIME_EXCEEDED = 11;
/**
* Answers to an incoming ICMP ECHO.
*
* @param pay
*/
private static void answerToEcho(Payload pay)
{
// if (Debug.enabled)
// Debug.println("ECHO REPLY to: " + IP.ipIntToString(IPPacket.getSrcAddr(pay)), Debug.DBG_ICMP);
if (Debug.enabled)
Debug.println("ECHO REPLY", Debug.DBG_ICMP);
ICMPPacket.setType(pay, TYPE_ECHO_REPLY);
IP.asyncSendPayload(pay, IPPacket.getSrcAddr(pay), IP.PROT_ICMP);
}
/**
* Answers ICMP DESTINATION UNREACHABLE.
*
* @param pay
* @param code
*/
protected static void sendDestUnreach(Payload pay, int code)
{
// if (Debug.enabled)
// Debug.println("DEST UNREACHABLE to: " + IP.ipIntToString(IPPacket.getSrcAddr(pay)), Debug.DBG_ICMP);
if (Debug.enabled)
Debug.println("DEST UNREACHABLE", Debug.DBG_ICMP);
ICMPPacket.ipToICMPPacket(pay);
ICMPPacket.setType(pay, ICMP.TYPE_DEST_UNREACH);
ICMPPacket.setCode(pay, code);
IP.asyncSendPayload(pay, IPPacket.getSrcAddr(pay), IP.PROT_ICMP);
}
/**
* Answers ICMP SOURCE QUENCHE.
*
* TODO: call this function if we have to close the TCP window
*
* @param pay
*/
protected static void sendSrcQuenche(Payload pay)
{
// if (Debug.enabled)
// Debug.println("SOURCHE QUENCHE to: " + IP.ipIntToString(IPPacket.getSrcAddr(pay)), Debug.DBG_ICMP);
if (Debug.enabled)
Debug.println("SOURCHE QUENCHE ", Debug.DBG_ICMP);
ICMPPacket.ipToICMPPacket(pay);
ICMPPacket.setType(pay, ICMP.TYPE_SRC_QUENCH);
IP.asyncSendPayload(pay, IPPacket.getSrcAddr(pay), IP.PROT_ICMP);
}
/**
* Answers ICMP TIME EXCEEDED.
*
* @param pay
*/
protected static void sendTimeExceeded(Payload pay)
{
// if (Debug.enabled)
// Debug.println("TIME EXCEEDED to: " + IP.ipIntToString(IPPacket.getSrcAddr(pay)), Debug.DBG_ICMP);
if (Debug.enabled)
Debug.println("TIME EXCEEDED ", Debug.DBG_ICMP);
ICMPPacket.ipToICMPPacket(pay);
ICMPPacket.setType(pay, ICMP.TYPE_TIME_EXCEEDED);
ICMPPacket.setCode(pay, 1); // 1: fragment reassembly time exceeded.
IP.asyncSendPayload(pay, IPPacket.getSrcAddr(pay), IP.PROT_ICMP);
}
/**
* By now we just print (if Debug.enabled == true) the information, that an IP packet
* hasn't reached its destination.
*
* TODO: do something if one of our IP packets has not reached its destination
*
* @param pay
*/
private static void handleDestUnreach(Payload pay)
{
byte code = ICMPPacket.getCode(pay);
ICMPPacket.icmpToIPPacket(pay);
if (Debug.enabled)
switch (code)
{
case 0: // net unreachable;
Debug.println("The network of the IP address ",Debug.DBG_ICMP);
// + IP.ipIntToString(IPPacket.getDestAddr(pay)) + " is unreachable",
// Debug.DBG_ICMP);
break;
case 1: // host unreachable;
Debug.println("The host with the IP address ",Debug.DBG_ICMP);
// + IP.ipIntToString(IPPacket.getDestAddr(pay)) + " is unreachable",
// Debug.DBG_ICMP);
break;
case 2: // protocol unreachable;
Debug.println("The protocol " ,Debug.DBG_ICMP);
// + IPPacket.getProtocol(pay) + "is unreachable",
// Debug.DBG_ICMP);
break;
case 3: // port unreachable;
Debug.println("The port IP address ",Debug.DBG_ICMP);
// + IP.ipIntToString(IPPacket.getDestAddr(pay))
// + ":" + UDPPacket.getDestPort(pay) + " is unreachable", Debug.DBG_ICMP);
break;
case 4: // fragmentation needed and DF set;
Debug.println("Fragmentation is needed but the Don't Fragment flag is set",
Debug.DBG_ICMP);
break;
case 5: // source route failed.
Debug.println("Source route failed", Debug.DBG_ICMP);
break;
}
}
/**
* Handles an incoming ICMP packet.
*
* @param pay
*/
protected static void receivePayload(Payload pay)
{
if (Debug.enabled)
Debug.println("ICMP received",Debug.DBG_ICMP);
// Debug.println("Type: " + ICMPPacket.getType(pay) + " Code: " + ICMPPacket.getCode(pay), Debug.DBG_ICMP);
switch (ICMPPacket.getType(pay))
{
case TYPE_ECHO:
answerToEcho(pay);
break;
case TYPE_DEST_UNREACH:
handleDestUnreach(pay);
Payload.freePayload(pay);
break;
default:
if (Debug.enabled)
Debug.println("Datagram unhandled...", Debug.DBG_ICMP);
Payload.freePayload(pay);
}
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/ICMPPacket.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/ICMPPacket.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: ICMPPacket.java
===================================================================
/*
* 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;
/**
* Interprets a Payload as ICMP packet. See RFC792
*
* @author Ulrich Feichter
* @author Tobias Kellner
* @author Christof Rath
* @version $Rev: 938 $ $Date: 2007/01/24 19:37:07 $
*/
public class ICMPPacket
{
/**
* Returns the ICMP type
*
* @param pay
* @return the type of an ICMP packet
*/
protected static byte getType(Payload pay)
{
return (byte) (pay.payload[0] >> 24);
}
/**
* Sets the ICMP type
*
* @param pay
* @param type
*/
protected static void setType(Payload pay, byte type)
{
pay.payload[0] &= 0x00FFFFFF;
pay.payload[0] |= type << 24;
}
/**
* Returns the code of an ICMP packet. The code is used to specify a certain
* ICMP type (e.g. Type 3 = 'destination unreachable' and Code 1 = 'host
* unreachable' or Code 3 = 'port unreachable'
*
* @param pay
* @return the code of an ICMP packet
*/
protected static byte getCode(Payload pay)
{
return (byte) (pay.payload[0] >> 16);
}
/**
* Sets the ICMP type
*
* @param pay
* @param code
*/
protected static void setCode(Payload pay, int code)
{
pay.payload[0] &= 0xFF00FFFF;
pay.payload[0] |= (code & 0xFF) << 16;
}
/**
* Get the Header Checksum. The checksum is calculated over the ICMP header
* and the data. The value is read from the ICMP header.
*
* @param pay
* The Payload
* @return The Header Checksum
*/
public static short getChecksum(Payload pay)
{
return (short) (pay.payload[0] & 0xFFFF);
}
/**
* Set the Header Checksum to the correct value. The checksum is calculated
* over the UDP header (+IP Pseudoheader) and the data (with the checksum
* field set to zero). The calculation is done in
* {@link UDPPacket#calculateChecksum}. The value is set in the UDP header.
*
* @param pay
* The Payload
*/
public static void setChecksum(Payload pay)
{
pay.payload[0] = pay.payload[0] & 0xFFFF0000;
pay.payload[0] = pay.payload[0] | (calculateChecksum(pay) & 0xFFFF);
}
/**
* Calculate the correct Checksum. The checksum is calculated over the ICMP
* header and the data (with the checksum field assumed to be zero).
*
* @param pay
* The Payload
* @return The Checksum
*/
public static short calculateChecksum(Payload pay)
{
// compute over ICMP Header and Payload, except the last bytes which
// don't
// fall on an int boundary
int packetLength = pay.length;
int cnt = packetLength / 4;
int i = 0;
int sum = 0;
int ofs = 0;
while (cnt != 0)
{
i = pay.payload[ofs];
sum += i & 0xFFFF;
sum += i >>> 16;
++ofs;
--cnt;
}
int modulo = packetLength % 4;
if (modulo != 0)
{
i = pay.payload[ofs];
// compute over the last int of the payload
switch (modulo)
{
case 1:
sum += (i >>> 16) & 0xFF00;
break;
case 2:
sum += (i >>> 16) & 0xFFFF;
break;
case 3:
sum += i & 0xFF00;
sum += (i >>> 16) & 0xFFFF;
}
}
while ((sum >> 16) != 0)
sum = (sum & 0xffff) + (sum >> 16);
sum = (~sum) & 0xffff;
return (short) sum;
}
/**
* Capsulates the original IP Datagram as part of some ICMP messages
* <b>Note:</b> The function trucenates the original IP datagram
*
* @param pay
*/
protected static void ipToICMPPacket(Payload pay)
{
int ofs = IPPacket.getIHL(pay);
for (int i = 0; i < 2; i++)
{
pay.payload[ofs + i + 2] = pay.payload[i]; // Two bytes of ICMP
// header...
pay.payload[i] = 0; // Clear the ICMP header fields
}
for (int i = 0; i < ofs; i++)
pay.payload[i + 2] = pay.ipHeader[i];
pay.length = (ofs + 4) * 4;
}
/**
* Restores the original IP Datagram as sent as part of some ICMP messages
* <b>Note:</b> The function destroys the ICMP Datagram
*
* @param pay
*/
protected static void icmpToIPPacket(Payload pay)
{
byte i;
for (i = 2; i < pay.length / 4 - 2; i++)
pay.ipHeader[i - 2] = pay.payload[i];
for (byte j = i; j < pay.length / 4; j++)
pay.payload[j - i] = pay.payload[j];
pay.length -= 8;
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/IP.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/IP.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: IP.java
===================================================================
/*
* 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 util.Dbg;
import ejip.Net;
import ejip.Packet;
import ejip.jtcpip.util.Debug;
import ejip.jtcpip.util.NumFunctions;
/**
* Represents the network layer. Contains methods for Packet sending and
* receiving (including reassembly). Received Packets are then handed to the
* upper (transport) layer.
*
* @see ejip2.jtcpip.TCP
* @see ejip2.jtcpip.UDP
*
* @author Tobias Kellner
* @author Ulrich Feichter
* @author Christof Rath
* @version $Rev: 994 $ $Date: 2007/01/24 19:37:07 $
*/
public class IP {
/** Default Time To Live Value */
private static final byte TTL = (byte) 128;
/** Protocol Constant for IP Header: ICMP */
public static final byte PROT_ICMP = 1;
/** Protocol Constant for IP Header: TCP */
public static final byte PROT_TCP = 6;
/** Protocol Constant for IP Header: UDP */
public static final byte PROT_UDP = 17;
/**
* Packet identification for IP Header. Incremented after each send. (From a
* security point of view, this is questionable) TODO
*/
private static short packetID = 0;
/** Exception that gets thrown when there is an error in the IP Address */
private static JtcpipException ipException;
public static void init() {
ipException = new JtcpipException("Invalid IP Address String");
}
/**
* Stores the content of a fragment into a reassembling payload
*
* @param rsmblPay
* @param fragmtPay
*/
private static void rsmblStore(Payload rsmblPay, Payload fragmtPay) {
int pLen = IPPacket.getLength(fragmtPay) - IPPacket.getIHL(fragmtPay)
* 4;
int ofs = IPPacket.getFragOfs(fragmtPay) * 2;
int maxIndex = NumFunctions.divRoundUp(pLen, 4);
if (ofs + maxIndex > rsmblPay.payload.length) {
// if (Debug.enabled)
// Debug
// .println(
// "Reassembled Payload would be greater than max. Payload size!
// Offset: "
// + ofs + " max. index: " + maxIndex
// + " Payload.length: "
// + rsmblPay.payload.length, Debug.DBG_IP);
ICMP.sendDestUnreach(rsmblPay, 4); // fragmentation needed and DF
// set;
return;
}
/*
* To prevent data overwriting (as for the first call rsmblPay ==
* fragmtPay) we copy the data back to front
*/
switch (pLen % 4) {// copy the last bytes but don't overwrite the
// previous content
case 1:
fragmtPay.payload[maxIndex] &= 0xFF000000;
rsmblPay.payload[ofs + maxIndex] &= 0x00FFFFFF;
rsmblPay.payload[ofs + maxIndex] |= fragmtPay.payload[maxIndex];
break;
case 2:
fragmtPay.payload[maxIndex] &= 0xFFFF0000;
rsmblPay.payload[ofs + maxIndex] &= 0x0000FFFF;
rsmblPay.payload[ofs + maxIndex] |= fragmtPay.payload[maxIndex];
break;
case 3:
fragmtPay.payload[maxIndex] &= 0xFFFFFF00;
rsmblPay.payload[ofs + maxIndex] &= 0x000000FF;
rsmblPay.payload[ofs + maxIndex] |= fragmtPay.payload[maxIndex];
break;
}
for (int i = pLen / 4 - 1; i >= 0; i--)
rsmblPay.payload[ofs + i] = fragmtPay.payload[i];
// if the offset == 0 the first fragment is stored and we can send an
// ICMP message in case of a time out
rsmblPay.setOffset(IPPacket.getFragOfs(fragmtPay));
rsmblPay.reassembledBitMap.setBits(IPPacket.getFragOfs(fragmtPay),
pLen / 8);
if (!IPPacket.isMFSet(fragmtPay)) {// last fragment => calculate bytes
// of unfragmented packet
rsmblPay.length = pLen + IPPacket.getFragOfs(fragmtPay) * 8;
// Only the very last datablock that doesn't fall on an eight byte
// boundary _may_ mark a block in the bitmap (else we wait for a
// fragment
// that holds the complete datablock)
if (pLen % 8 > 0)
rsmblPay.reassembledBitMap.setBit(IPPacket
.getFragOfs(fragmtPay)
+ (pLen / 8));
}
if (Debug.enabled && (Debug.dbgFlagsToDisplay & Debug.DBG_IP) > 0)
rsmblPay.reassembledBitMap.print();
}
/**
* Handles the reassembling of a IP packet fragment
*
* @param pay
*/
private static void reassemblePayload(Payload pay) {
for (int i = 0; i < StackParameters.PAYLOAD_POOL_SIZE; i++) {
if (Payload.pool[i] != null
&& Payload.pool[i].getStatus() == Payload.PAYLOAD_RESMBL
&& (IPPacket.getID(pay) == IPPacket.getID(Payload.pool[i]))) { // just
// received
// a
// packet
// with
// the
// same
// ID
rsmblStore(Payload.pool[i], pay);
Payload.freePayload(pay);
// if (Debug.enabled)
// if (Payload.pool[i].length != -1)
// Debug.println("Seeing if all "
// + NumFunctions.divRoundUp(
// Payload.pool[i].length, 8)
// + " bits are set", Debug.DBG_IP);
if (Payload.pool[i].length != -1 // length is -1 until we got
// the last fragment.
&& Payload.pool[i].reassembledBitMap
.allSet(NumFunctions.divRoundUp(
Payload.pool[i].length, 8))) {
Payload.pool[i].setStatus(Payload.PAYLOAD_USED, 0);
//handlePayload(Payload.pool[i]);
byte prot = IPPacket.getProtocol(Payload.pool[i]);
switch (prot) {
case PROT_TCP:
TCP.receivePayload(Payload.pool[i]);
break;
case PROT_UDP:
UDP.receivePayload(Payload.pool[i]);
break;
case PROT_ICMP:
ICMP.receivePayload(Payload.pool[i]);
break;
}
}
return;
}
}
// No matching payload found => this is the first part of a fragmented
// payload
pay.length = -1; // the payload length is invalid until we got the
// last fragment
pay.setStatus(Payload.PAYLOAD_RESMBL,
StackParameters.REASSEMBLE_TIMEOUT);
pay.setOffset(StackParameters.PAYLOAD_MAX_DATA_SIZE); // No fragments
// stored yet
rsmblStore(pay, pay); // move the payload to the correct position
}
/**
* Hands a Packet to the upper (transport) layer. Which layer that is is
* read from the Protocol entry in the IP header. If the protocol is unknown
* (not handled), the packet is dropped.
*
* NOTE: this function has been inlined!!
*
* @param pay
* Packet
*/
private static void handlePayload(Payload pay) {
byte prot = IPPacket.getProtocol(pay);
switch (prot) {
case PROT_TCP:
TCP.receivePayload(pay);
break;
case PROT_UDP:
UDP.receivePayload(pay);
break;
case PROT_ICMP:
ICMP.receivePayload(pay);
break;
}
}
/**
* Copies the data stored in a <code>Payload</code> object to a
* <code>Packet</code> object. Also sets the protocol field in the
* Ethernet header to IP.
*
* @param pay
* Payload to copy from
* @param p
* Packet to write to
*
* @return Zero if the full payload fitted into the packet else the number
* of already copied bytes
*/
protected static int payloadToPacket(Payload pay, Packet p) {
return payloadToPacket(pay, p, 0);
}
/**
* Copies the data (up to the size of a Ethernet packet) stored in a
* <code>Payload</code> object to a <code>Packet</code> object. Also
* sets the protocol field in the Ethernet header to IP.
*
* @param pay
* Payload to copy from
* @param p
* Packet to write to
* @param offset
* in 4-byte-blocks (i.e. already sent blocks)
* @return The offset where the data for the next Packet starts (if
* fragmentation needed, else 0)
*/
protected static int payloadToPacket(Payload pay, Packet p, int offset) {
byte headerLength = IPPacket.getIHL(pay);
boolean isFragmt = (pay.length + headerLength * 4) > p.buf.length * 4
&& pay.getStatus() != Payload.PAYLOAD_ARP_WT;
if (isFragmt && IPPacket.isDFSet(pay)) {
ICMP.sendDestUnreach(pay, 4); // Code 4: fragmentation needed and
// DF set
return 0;
}
/*
* if (isFragmt && (offset % 2 != 0)) //Should not be needed anymore {
* if (Debug.enabled) Debug.println("ALERT! Fragment not on boundary",
* Debug.DBG_IP); offset--; // Fragmentation Offset not on an 8-byte
* boundary -> overlap }
*/
int dataInPayload = headerLength * 4 + pay.length - offset * 4; // Size
// of
// the
// (rest
// of
// the)
// payload
p.len = Math.min(p.buf.length * 4, dataInPayload);
p.llh[6] = 0x0800; // IP code for ethernet header
if (isFragmt) // IP Fragmentation!
{
if (p.len == dataInPayload) // Last fragment of the Payload
IPPacket.clearMF(pay);
else {
p.len -= (p.len - headerLength * 4) % 8; // Fragmentation
// offset - 8 byte
// boundary!
IPPacket.setMF(pay);
}
IPPacket.setLength(pay, (short) p.len);
IPPacket.setFragOfs(pay, (short) (offset / 2));
}
IPPacket.setChecksum(pay);
// copy the IP header into the Ethernet packet
for (byte i = 0; i < headerLength; i++)
p.buf[i] = pay.ipHeader[i];
int i = 0;
int lastPayloadIndex = NumFunctions.divRoundUp(pay.length, 4);
int limit = Math.min(NumFunctions.divRoundUp(p.len, 4) - headerLength,
lastPayloadIndex - offset);
for (i = 0; i < limit; i++)
p.buf[i + headerLength] = pay.payload[offset + i];
// TODO: maybe padding if too short
if (p.len == dataInPayload)
return 0;
return offset + 1;
// return p.len == dataInPayload ? 0 : offset + i; // if the size of the
// (rest of the) payload
// == the packet length
// return 0 else the
// offset
}
/**
* Takes a newly received Packet from the network driver. The content is
* then stored in a <code>Payload</code> object. If the Packet is valid
* (checksum, ehternet header...) it will be delivered to to the next layer
* (via {@link IP#handlePayload}). If a packet is fragmented, it will be
* reassembled here. <b>Note:</b> After the method returns, the passed
* Packet will be marked as FREE!
*
* @see #handlePayload
* @param p
* Packet to process
*/
public static void receivePacket(Packet p) {
if (Debug.enabled)
Debug.println("Received a packet", Debug.DBG_IP);
if (p.len < 20) {
if (Debug.enabled)
Debug.println("Packet is shorter than 20 bytes, dropping!!",
Debug.DBG_IP);
p.setStatus(Packet.FREE);
return;
}
if (p.llh[6] != 0x0800) {
if (Debug.enabled)
Debug.println("PACKET IS NOT AN IP PACKET!!", Debug.DBG_IP);
p.setStatus(Packet.FREE);
return;
}
Payload pay = Payload.newPayload();
if (pay == null) {
if (Debug.enabled)
Debug.println("No more Payloads available - packet dropped",
Debug.DBG_IP);
p.setStatus(Packet.FREE);
return;
}
for (int i = 0; i < 5; i++)
// copy first 20 byte of header to ipHeader (therefore we are not
// able do read out IPPacket.getIHL(pay))
pay.ipHeader[i] = p.buf[i];
// accept only packets for our ip or eth broadcasts
if (IPPacket.getDestAddr(pay) != Net.linkLayer.getIpAddress()
&& !(p.llh[0] == 0xFFFF && p.llh[1] == 0xFFFF && p.llh[2] == 0xFFFF)) {
// System.out.println(IPPacket.getDestAddr(pay));
// System.out.println(Net.linkLayer.ip);
if (Debug.enabled)
Debug.println("Packet is not for us... dropping", Debug.DBG_IP);
p.setStatus(Packet.FREE);
Payload.freePayload(pay);
return;
}
int headerLength = (int) (IPPacket.getIHL(pay) & 0xFF);
if (headerLength > 5) // if header is longer than 20 byte copy the
// rest
for (int i = 5; i < headerLength; i++)
pay.ipHeader[i] = p.buf[i];
// if (Debug.enabled)
// Debug.println("Captured packet length: ", Debug.DBG_IP);
// check if the packet length is acceptable, drop the packet if wrong
int payloadLengtFromIPHeader = ((int) (IPPacket.getLength(pay) & 0xFFFF) - headerLength * 4);
if (payloadLengtFromIPHeader > p.len - headerLength * 4
|| payloadLengtFromIPHeader > StackParameters.PAYLOAD_MAX_DATA_SIZE) {
if (Debug.enabled)
Debug.println("Packet is too long, dropping", Debug.DBG_IP);
p.setStatus(Packet.FREE);
Payload.freePayload(pay);
return;
}
for (int i = 0; i < (NumFunctions.divRoundUp(p.len, 4) - headerLength); i++) // copy
// payload
{
pay.payload[i] = p.buf[i + headerLength];
// if (Debug.enabled)
// Debug.print(Debug.intToHexString(pay.payload[i]), Debug.DBG_IP);
}
// Take the min of the length specified in the IP header and the real
// captured data as Payload length
pay.length = payloadLengtFromIPHeader;
p.setStatus(Packet.FREE);
if (!IPPacket.isValidPacket(pay)) {
if (Debug.enabled)
Debug.println("Checksum not valid; dropping packet",
Debug.DBG_IP);
Payload.freePayload(pay);
return;
}
if (IPPacket.isMFSet(pay) || IPPacket.getFragOfs(pay) != 0) {
if (Debug.enabled)
Debug.println("Valid Packet, FRAGMENTED", Debug.DBG_IP);
reassemblePayload(pay);
} else { // not fragmented
if (Debug.enabled)
Debug.println("Valid Packet, not fragmented", Debug.DBG_IP);
// TODO: inlined
//handlePayload(pay);
byte prot = IPPacket.getProtocol(pay);
switch (prot) {
case PROT_TCP:
TCP.receivePayload(pay);
break;
case PROT_UDP:
UDP.receivePayload(pay);
break;
case PROT_ICMP:
ICMP.receivePayload(pay);
break;
}
}
/*
* if (Debug.enabled){ Debug.println("version " +
* IPPacket.getVersion(pay)); Debug.println("ihl " +
* IPPacket.getIHL(pay)); Debug.println("tos " +
* Debug.IntegerToHexString(IPPacket.getToS(pay)));
* Debug.println("length: " + IPPacket.getLength(pay));
* Debug.println("id: " + IPPacket.getID(pay)); Debug.println("res: " +
* IPPacket.isReservedSet(pay)); Debug.println("fragm: " +
* IPPacket.isDFSet(pay)); Debug.println("more frag: " +
* IPPacket.isMFSet(pay)); Debug.println("frag ofs: " +
* IPPacket.getFragOfs(pay)); Debug.println("ttl: " +
* IPPacket.getTTL(pay)); Debug.println("protocol: " +
* Debug.IntegerToHexString(IPPacket.getProtocol(pay)));
* Debug.println("src: " +
* Debug.IntegerToHexString(IPPacket.getSrcAddr(pay)));
* Debug.println("dest addr: " +
* Debug.IntegerToHexString(IPPacket.getDestAddr(pay))); }
*/
}
/**
* Prepares the IP header. In order to send a packet
*
* @param pay
* The packet payload
* @param destIP
* The destination IP
* @param protocol
* The transport protocol id
*/
private static void prepareIPPacket(Payload pay, int destIP, byte protocol) {
IPPacket.setIHL(pay, (byte) 0x5);
IPPacket.setToS(pay, (byte) 0x0);
IPPacket
.setLength(pay, (short) (pay.length + IPPacket.getIHL(pay) * 4));
IPPacket.setID(pay, packetID++);
IPPacket.clearDF(pay);
IPPacket.clearMF(pay);
IPPacket.clearReserved(pay);
IPPacket.setFragOfs(pay, (short) 0x0);
IPPacket.setTTL(pay, (byte) TTL);
IPPacket.setProtocol(pay, protocol);
if ((destIP >= 2130706432) && (destIP <= 2147483647)) // 127.0.0.0/8
{
IPPacket.setDestAddr(pay, Net.linkLayer.getIpAddress()); // Swapping
// addresses for
// loopback
IPPacket.setSrcAddr(pay, destIP);
} else {
IPPacket.setDestAddr(pay, destIP);
IPPacket.setSrcAddr(pay, Net.linkLayer.getIpAddress());
}
switch (IPPacket.getProtocol(pay)) {
case PROT_TCP:
TCPPacket.setChecksum(pay);
break;
case PROT_UDP:
UDPPacket.setChecksum(pay);
break;
case PROT_ICMP:
ICMPPacket.setChecksum(pay);
break;
}
}
/**
* @deprecated
*
* Sends a Packet by handing it to the network driver. Takes a payload, a
* destination ip and a protocol number (e.g. <code>IP.PROT_TCP</code>).
* <b>Note:</b> After the method returns, the passed Payload will be marked
* as free!
*
* @param pay
* The packet payload
* @param destIP
* The destination IP
* @param protocol
* The transport protocol id
*
* @return Whether send was successful
*/
public static boolean sendPayload(Payload pay, int destIP, byte protocol) {
prepareIPPacket(pay, destIP, protocol);
if (pay.length > StackParameters.PACKET_MTU_SIZE) {
// TODO: Implement fragmentation here? Would this make sense?
if (Debug.enabled)
Debug.println("Fragmentation not implemented here!",
Debug.DBG_IP);
return false;
}
Packet p = Packet.getPacket(Packet.FREE, Packet.ALLOC, Net.linkLayer);
if (p == null)
return false; // TODO: Retransmit
payloadToPacket(pay, p);
Payload.freePayload(pay);
p.setStatus(Packet.SND);
return true;
}
/**
* Prepares and marks a Payload for sending
*
* @param pay
* The packet payload
* @param destIP
* The destination IP
* @param protocol
* The transport protocol id
*/
public synchronized static void asyncSendPayload(Payload pay, int destIP,
byte protocol) {
if (Debug.enabled)
Debug.println("asyncSendPayload", Debug.DBG_IP);
prepareIPPacket(pay, destIP, protocol);
if (Debug.enabled)
Debug.println("asyncSendPayload2", Debug.DBG_IP);
pay.setStatus(Payload.PAYLOAD_SND_RD, 0);
if (Debug.enabled)
Debug.println("asyncSendPayload3", Debug.DBG_IP);
}
/**
* Converts an IP address of the format [xx]x.[xx]x.[xx]x.[xx]x to an
* integer. Throws an exception if the format of the String is faulty.
*
* @param ipAddr
* The IP address String
* @return The IP address as an int
* @throws JtcpipException
* Invalid IP Address String
*/
public static int ipStringToInt(String ipAddr) throws JtcpipException {
byte dots = 0;
short ipOctet = 0;
int ipInt = 0;
for (int i = 0; i <= ipAddr.length(); i++) {
if (i == ipAddr.length() || ipAddr.charAt(i) == '.') {
if (i < ipAddr.length() && ++dots == 4) {
// if (Debug.enabled)
// Debug.println("Too many dots in " + ipAddr,
// Debug.DBG_IP);
throw ipException;
}
if (ipOctet < 0 || ipOctet > 255) {
// if (Debug.enabled)
// Debug.println("Wrong IP values in " + ipAddr,
// Debug.DBG_IP);
throw ipException;
}
ipInt = (ipInt << 8) | (ipOctet & 0xFF);
ipOctet = 0;
} else if (ipAddr.charAt(i) >= '0' && ipAddr.charAt(i) <= '9')
ipOctet = (short) (ipOctet * 10 + (ipAddr.charAt(i) - '0'));
else {
if (Debug.enabled)
Debug.println("Wrong char in IP address ", Debug.DBG_IP);
throw ipException;
}
}
if (dots != 3) {
if (Debug.enabled)
Debug.println("IP address too short ", Debug.DBG_IP);
throw ipException;
}
return ipInt;
}
/**
* @param ipAddr
* @return the String representation of an IP address
*/
public static String ipIntToString(int ipAddr) {
return "" + ((ipAddr >>> 24) & 0xFF) + "." + ((ipAddr >>> 16) & 0xFF)
+ "." + ((ipAddr >>> 8) & 0xFF) + "." + ((ipAddr) & 0xFF);
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/IPPacket.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/IPPacket.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: IPPacket.java
===================================================================
/*
* 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;
/**
* The IP Packet Class encapsulating methods to handle a Payload as an IP
* Packet. All methods are static and get a {@link Payload} as a parameter.
* There are get and set methods for all fields of the IP header.
*
* @author Tobias Kellner
* @author Ulrich Feichter
* @author Christof Rath
* @version $Rev: 849 $ $Date: 2007/01/24 19:37:07 $
*/
public class IPPacket
{
/** Position of the Reserved Flag in the 2nd word of the IP header */
private static final int RESERVED_MASK = 0x8000;
/** Position of the Don't Fragment Flag in the 2nd word of the IP header */
private static final int DF_MASK = 0x4000;
/** Position of the More Fragments Flag in the 2nd word of the IP header */
private static final int MF_MASK = 0x2000;
/**
* Get the IP Version. Should be 4 for IPv4
*
* @param pay
* The Payload
* @return The IP Version
*/
public static byte getVersion(Payload pay)
{
return (byte) (pay.ipHeader[0] >>> 28);
}
/**
* Set the IP Version Should be 4 for IPv4
*
* @param pay
* The Payload
* @param ver
* The IP Version to set
*/
public static void setVersion(Payload pay, byte ver)
{
int i = pay.ipHeader[0] & 0x0FFFFFFF;
pay.ipHeader[0] = i | ((ver & 0xF) << 28);
}
/**
* Get the Internet Header Length. This is the size of the IP header in
* 32-bit words. (min. 5, max. 15)
*
* @param pay
* The Payload
* @return The Internet Header Length
*/
public static byte getIHL(Payload pay)
{
return (byte) ((pay.ipHeader[0] >>> 24) & 0x0F);
}
/**
* Set the Internet Header Length. This is the size of the IP header in
* 32-bit words. (min. 5, max. 15)
*
* @param pay
* The Payload
* @param len
* The Internet Header Length
*/
public static void setIHL(Payload pay, byte len)
{
int i = pay.ipHeader[0] & 0xF0FFFFFF;
pay.ipHeader[0] = i | ((len & 0xF) << 24);
}
/**
* Get the Type of Service.
* <ul>
* <li> bits 0-2: precedence
* <li> bit 3: 0 = Normal Delay, 1 = Low Delay
* <li> bit 4: 0 = Normal Throughput, 1 = High Throughput
* <li> bit 5: 0 = Normal Reliability, 1 = High Reliability
* <li> bits 6-7: Reserved for future use
* </ul>
*
* @param pay
* The Payload
* @return The Type of Service
*/
public static byte getToS(Payload pay)
{
return (byte) ((pay.ipHeader[0] >>> 16) & 0xFF);
}
/**
* Set the Type of Service.
* <ul>
* <li> bits 0-2: precedence
* <li> bit 3: 0 = Normal Delay, 1 = Low Delay
* <li> bit 4: 0 = Normal Throughput, 1 = High Throughput
* <li> bit 5: 0 = Normal Reliability, 1 = High Reliability
* <li> bits 6-7: Reserved for future use
* </ul>
*
* @param pay
* The Payload
* @param tos
* The Type of Service
*/
public static void setToS(Payload pay, byte tos)
{
int i = pay.ipHeader[0] & 0xFF00FFFF;
pay.ipHeader[0] = i | ((tos & 0xFF) << 16);
}
/**
* Get the Total Length of the Packet. Entire size of the datagram,
* including header and data, in bytes. (min. 20, max. 65535)
*
* @param pay
* The Payload
* @return The Total Length
*/
public static short getLength(Payload pay)
{
return (short) (pay.ipHeader[0] & 0xFFFF);
}
/**
* Set the Total Length of the Packet. Entire size of the datagram,
* including header and data, in bytes. (min. 20, max. 65535)
*
* @param pay
* The Payload
* @param len
* The Total Length
*/
public static void setLength(Payload pay, short len)
{
int i = pay.ipHeader[0] & 0xFFFF0000;
pay.ipHeader[0] = i | (len & 0xFFFF);
}
/**
* Get the Identification. Used for uniquely identifying individual
* fragments of a fragmented IP Packet.
*
* @param pay
* The Payload
* @return The Identification
*/
public static short getID(Payload pay)
{
return (short) (pay.ipHeader[1] >>> 16);
}
/**
* Set the Identification. Used for uniquely identifying individual
* fragments of a fragmented IP Packet.
*
* @param pay
* The Payload
* @param id
* The Identification
*/
public static void setID(Payload pay, short id)
{
int i = pay.ipHeader[1] & 0x0000FFFF;
pay.ipHeader[1] = i | ((id & 0xFFFF) << 16);
}
/**
* Check whether the Reserved Flag is set. This Flag must be zero. <b>Note:</b>
* because this is a benign IP Stack, setting this flag is not possible.
*
* @param pay
* The Payload
* @return Whether the Reserved Flag is set
*/
public static boolean isReservedSet(Payload pay)
{
return (pay.ipHeader[1] & RESERVED_MASK) != 0;
}
/**
* Clear the Reserved Flag. This Flag must be zero. <b>Note:</b> because
* this is a benign IP Stack, setting this flag is not possible.
*
* @param pay
* The Payload
*/
public static void clearReserved(Payload pay)
{
pay.ipHeader[1] = pay.ipHeader[1] & ~RESERVED_MASK;
}
/**
* Check whether the Don't Fragment Flag is set. A Packet with DF set must
* not be fragmented. If it would have to be, it is dropped instead.
*
* @param pay
* The Payload
* @return Whether the Don't Fragment Flag is set
*/
public static boolean isDFSet(Payload pay)
{
return (pay.ipHeader[1] & DF_MASK) != 0;
}
/**
* Set the Don't Fragment Flag. A Packet with DF set must not be fragmented.
* If it would have to be, it is dropped instead.
*
* @param pay
* The Payload
*/
public static void setDF(Payload pay)
{
pay.ipHeader[1] = pay.ipHeader[1] | DF_MASK;
}
/**
* Clear the Don't Fragment Flag. A Packet with DF set must not be
* fragmented. If it would have to be, it is dropped instead.
*
* @param pay
* The Payload
*/
public static void clearDF(Payload pay)
{
pay.ipHeader[1] = pay.ipHeader[1] & ~DF_MASK;
}
/**
* Check whether the More Fragments Flag is set. In a fragmented IP Packet,
* all split Packets except the last one have this flag set.
*
* @param pay
* The Payload
* @return Whether the More Fragments Flag is set
*/
public static boolean isMFSet(Payload pay)
{
return (pay.ipHeader[1] & MF_MASK) != 0;
}
/**
* Set the More Fragments Flag. In a fragmented IP Packet, all split Packets
* except the last one have this flag set.
*
* @param pay
* The Payload
*/
public static void setMF(Payload pay)
{
pay.ipHeader[1] = pay.ipHeader[1] | MF_MASK;
}
/**
* Clear the More Fragments Flag. In a fragmented IP Packet, all split
* Packets except the last one have this flag set.
*
* @param pay
* The Payload
*/
public static void clearMF(Payload pay)
{
pay.ipHeader[1] = pay.ipHeader[1] & ~MF_MASK;
}
/**
* Get the Fragment Offset. The place of a particular fragment in the
* original IP datagram, measured in units of 8-byte blocks.
*
* @param pay
* The Payload
* @return The Fragment Offset
*/
public static short getFragOfs(Payload pay)
{
return (short) (pay.ipHeader[1] & 0x1FFF);
}
/**
* Set the Fragment Offset. The place of a particular fragment in the
* original IP datagram, measured in units of 8-byte blocks.
*
* @param pay
* The Payload
* @param ofs
* The Fragment Offset
*/
public static void setFragOfs(Payload pay, short ofs)
{
int i = pay.ipHeader[1] & 0xFFFFE000;
pay.ipHeader[1] = i | (ofs & 0x1FFF);
}
/**
* Get the Time To Live. Each packet switch (or router) that a datagram
* crosses decrements the TTL field by one. When the TTL field hits zero,
* the Packet is no longer forwarded by a packet switch and is discarded.
*
* @param pay
* The Payload
* @return The Time To Live
*/
public static byte getTTL(Payload pay)
{
return (byte) (pay.ipHeader[2] >>> 24);
}
/**
* Set the Time To Live. Each packet switch (or router) that a datagram
* crosses decrements the TTL field by one. When the TTL field hits zero,
* the Packet is no longer forwarded by a packet switch and is discarded.
*
* @param pay
* The Payload
* @param ttl
* The Time To Live
*/
public static void setTTL(Payload pay, byte ttl)
{
int i = pay.ipHeader[2] & 0x00FFFFFF;
pay.ipHeader[2] = i | ((ttl & 0xFF) << 24);
}
/**
* Get the Protocol. The protocol used in the data part of the datagram.
*
* @see IP#PROT_ICMP
* @see IP#PROT_TCP
* @see IP#PROT_UDP
*
* @param pay
* The Payload
* @return The Protocol
*/
public static byte getProtocol(Payload pay)
{
return (byte) ((pay.ipHeader[2] >>> 16) & 0xFF);
}
/**
* Set the Protocol. The protocol used in the data part of the datagram.
*
* @see IP#PROT_ICMP
* @see IP#PROT_TCP
* @see IP#PROT_UDP
*
* @param pay
* The Payload
* @param proto
* The Protocol
*/
public static void setProtocol(Payload pay, byte proto)
{
int i = pay.ipHeader[2] & 0xFF00FFFF;
pay.ipHeader[2] = i | ((proto & 0xFF) << 16);
}
/**
* Get the Header Checksum. The checksum is calculated over the IP Header.
*
* @param pay
* The Payload
* @return The Header Checksum
*/
public static short getChecksum(Payload pay)
{
return (short) (pay.ipHeader[2] & 0xFFFF);
}
/**
* Set the Header Checksum to the correct value. The checksum is calculated
* over the IP Header (with the checksum field assumed to be zero). The
* calculation is done in {@link IPPacket#calculateChecksum}.
*
* @param pay
* The Payload
*/
public static void setChecksum(Payload pay)
{
pay.ipHeader[2] = pay.ipHeader[2] & 0xFFFF0000;
pay.ipHeader[2] = pay.ipHeader[2] | (calculateChecksum(pay) & 0xFFFF);
}
/**
* Get the Source address. The IP address the Packet originated from.
*
* @param pay
* The Payload
* @return The Source address as 32-bit value
*/
public static int getSrcAddr(Payload pay)
{
return pay.ipHeader[3];
}
/**
* Set the Source address. The IP address the Packet originated from.
*
* @param pay
* The Payload
* @param addr
* The Source address as 32-bit value
*/
public static void setSrcAddr(Payload pay, int addr)
{
pay.ipHeader[3] = addr;
}
/**
* Get the Destination address. The IP address the Packet is headed to.
*
* @param pay
* The Payload
* @return The Destination address as 32-bit value
*/
public static int getDestAddr(Payload pay)
{
return pay.ipHeader[4];
}
/**
* Set the Destination address. The IP address the Packet is headed to.
*
* @param pay
* The Payload
* @param addr
* The Destination address as 32-bit value
*/
public static void setDestAddr(Payload pay, int addr)
{
pay.ipHeader[4] = addr;
}
/**
* Calculate the correct Checksum. The checksum is calculated over the IP
* Header (with the checksum field assumed to be zero).
*
* @param pay
* The Payload
* @return The Checksum
*/
public static short calculateChecksum(Payload pay)
{
int i;
int ofs = 0;
int sum = 0;
byte cnt = getIHL(pay);
while (cnt != 0)
{
i = pay.ipHeader[ofs];
sum += i & 0xffff;
sum += i >>> 16;
++ofs;
--cnt;
}
while ((sum >> 16) != 0)
sum = (sum & 0xffff) + (sum >> 16);
sum = (~sum) & 0xffff;
return (short) sum;
}
/**
* Check whether the checksum is valid.
*
* @param pay
* The Payload
* @return Whether the checksum is valid.
*/
public static boolean isChecksumValid(Payload pay)
{
return calculateChecksum(pay) == 0; // Checksum with checksum field
// correctly set should equal 0
}
/**
* Check whether the Packet is valid. Checks the checksum and whether the
* Reserved Flag is cleared.
*
* @param pay
* The Payload
* @return Whether the Packet is valid.
*/
public static boolean isValidPacket(Payload pay)
{
return (!isReservedSet(pay) && isChecksumValid(pay));
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/JtcpipException.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/JtcpipException.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: JtcpipException.java
===================================================================
/*
* 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.IOException;
/**
* TCP / IP Stack Exception.
*
* @author Tobias Kellner
* @author Ulrich Feichter
* @author Christof Rath
* @version $Rev: 849 $ $Date: 2007/01/24 19:37:07 $
*/
public class JtcpipException extends IOException
{
/** serial version UID - required for serialization */
private static final long serialVersionUID = 1L;
/**
* TCP / IP Stack Exception.
*
* @param errorMessage
* The error message
*/
public JtcpipException(String errorMessage)
{
super(errorMessage);
}
}
1.1 jop/java/target/src/common/ejip/jtcpip/NwLoopRtThread.java
http://www.opencores.org/cvsweb.shtml/jop/java/target/src/common/ejip/jtcpip/NwLoopRtThread.java?rev=1.1&content-type=text/x-cvsweb-markup
Index: NwLoopRtThread.java
===================================================================
/*
* 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 util.Dbg;
import joprt.RtThread;
import ejip.Arp;
import ejip.LinkLayer;
import ejip.Net;
import ejip.Packet;
import ejip.jtcpip.util.Debug;
/**
* Network loop class. Creates a thread for a given Net and LinkLayer instance
*
* @author Ulrich Feichter
* @author Tobias Kellner
* @author Christof Rath
* @version $Rev: 984 $ $Date: 2007/01/24 19:37:07 $
*/
public class NwLoopRtThread extends RtThread {
public static TCPConnection conn = null;
public static Payload pay = null;
/** Holds the instance for the singelton pattern */
private static NwLoopRtThread nwLoop;
/**
* Holds a references to the LinkLayer instances to call the
* LinkLayer.loop()
*/
private LinkLayer linkLayer;
/** counts the loop cycles up to StackParameters.NW_LOOP_CYCLES */
private int cycleCnt = 0;
/**
* if the cycleCnt % tcpModulus == 0 the next TCP connection is tested to
* send new data of the oStream
*/
private int tcpModulus = StackParameters.NW_LOOP_CYCLES
/ StackParameters.TCP_CONNECTION_POOL_SIZE;
/**
* Creates the network loop instance
*
* @param linkLayer
* Instances to the link layers
* @param msDelay
* Delay in milli seconds between two calls
*/
private NwLoopRtThread(LinkLayer linkLayer, int msDelay) {
super(10, 10000);
Packet.init();
this.linkLayer = linkLayer;
}
public void run() {
for (;;) {
// Dbg.wr("NWLOOP\n");
waitForNextPeriod();
if (cycleCnt % tcpModulus == 0) {
int conToTest = cycleCnt / tcpModulus;
if (TCPConnection.pool[conToTest] != null
&& TCPConnection.pool[conToTest].getState() != TCPConnection.STATE_CLOSED) {
if (!TCPConnection.pool[conToTest].pollConnection())
TCPConnection.retryToSendData = conToTest;
}
} else {
if (TCPConnection.retryToSendData > -1) {
if (TCPConnection.pool[TCPConnection.retryToSendData]
.pollConnection())
TCPConnection.retryToSendData = -1;
}
}
int cnt = Payload.waitingPayloadCount();
if (cnt > 0) {
byte status;
for (int i = 0; i < StackParameters.PAYLOAD_POOL_SIZE; i++) {
status = Payload.pool[i].getStatus();
if (status > Payload.PAYLOAD_WND_RX) {
cnt--;
switch (status) {
case Payload.PAYLOAD_FRAGMT:
case Payload.PAYLOAD_SND_RD:
if (preparedSend(Payload.pool[i])) {
// Everything ok -> free payload
Payload.freePayload(Payload.pool[i]);
}
break;
case Payload.PAYLOAD_ARP_WT:
if (Arp.inCache(IPPacket
.getDestAddr(Payload.pool[i]))) {
if (Payload.pool[i].getOffset() == 0)
Payload.pool[i].setStatus(
Payload.PAYLOAD_SND_RD, 0);
else
Payload.pool[i].setStatus(
Payload.PAYLOAD_FRAGMT,
Payload.pool[i].getOffset());
}
if (Payload.pool[i].isTimeout()) {
if (Debug.enabled)
Debug.println("ARP timeout!",
Debug.DBG_OTHER);
Payload.freePayload(Payload.pool[i]);
// No one to inform (ICMP) -> free payload
}
break;
case Payload.PAYLOAD_RESMBL:
if (Payload.pool[i].isTimeout()) {
if (Payload.pool[i].getOffset() == 0)
// The first fragment has been received
// -> So we can inform the remote host
ICMP.sendTimeExceeded(Payload.pool[i]);
else
Payload.freePayload(Payload.pool[i]);
// Just free the payload
}
break;
default:
if (Debug.enabled)
Debug.println("Unknown Payload status: ",
Debug.DBG_OTHER);
}
}
if (cnt <= 0)
break;
}
}
Packet p = Packet.getPacket(Packet.RCV, Packet.ALLOC);
if (p != null) {
IP.receivePacket(p);
Dbg.wr("Ip.receive returned\n");
}
if ((conn != null) && (pay != null)) {
TCP.sendPackets(conn, pay);
conn = null;
pay = null;
}
cycleCnt++;
if (cycleCnt >= StackParameters.NW_LOOP_CYCLES)
cycleCnt = 0;
}
}
/**
* Tries to send a payload that is in the PAYLOAD_SND_RD state
*
* @param pay
* @return true if the complete payload has been sent
*/
protected static boolean preparedSend(Payload pay) {
if (Debug.enabled)
Debug.println("prepared send", Debug.DBG_OTHER);
// TODO for Dhcp
// int firstHopDest = (LinkLayer.isSameSubnet(IPPacket.getDestAddr(pay))
// ? IPPacket
// .getDestAddr(pay)
// : Net.linkLayer.gateway);
int firstHopDest = IPPacket.getDestAddr(pay);
// System.out.println(IPPacket.getDestAddr(pay));
// FIXME: For LinkLayers that do not require ARP (e.g. Slip, Loopback)
// this has to be modified
boolean inCache = (Arp.inCache(firstHopDest)
|| (firstHopDest == Net.linkLayer.getIpAddress())
// loopback to same addr
|| (firstHopDest >= 2130706433 && firstHopDest <= 2147483646));
// loopback to 127.x.x.x
Packet p = Packet.getPacket(Packet.FREE, Packet.ALLOC, Net.linkLayer);
if (p == null)
return false;
if (!inCache)
pay.setStatus(Payload.PAYLOAD_ARP_WT, StackParameters.ARP_TIMEOUT);
int offset = 0;
if (inCache)
offset = pay.getOffset();
else
offset = Math.max(pay.length / 4 - 1, 0);
// int offset = inCache ? pay.getOffset() : Math
// .max(pay.length / 4 - 1, 0);
// // If ARP request use just the minimum of Payload
offset = IP.payloadToPacket(pay, p, offset);
if (firstHopDest == Net.linkLayer.getIpAddress() // loopback to same
// addr
|| (firstHopDest >= 2130706433 && firstHopDest <= 2147483646)) // loopback
// to
// 127.x.x.x
p.setStatus(Packet.RCV);
else {
if (!inCache && IPPacket.getDestAddr(pay) != firstHopDest) { // Request
// ARP
// resolution
// for
// gateway
// IP destination address (without gateway) is
// at position 4 for IP packets and at 6 for ARP packets
int addrPos = p.llh[6] == 0x0806 ? 6 : 4;
p.buf[addrPos] = firstHopDest;
}
p.setStatus(Packet.SND);
}
if (offset > 0)
pay.setStatus(Payload.PAYLOAD_FRAGMT, offset);
return inCache && offset == 0;
}
/**
* Creates and start the network loop thread
*
* @param linkLayer
* @return The instance of the network loop
*/
public static NwLoopRtThread createInstance(LinkLayer linkLayer) {
if (nwLoop == null) {
nwLoop = new NwLoopRtThread(linkLayer,
StackParameters.NW_LOOP_TIMEOUT);
// nwLoop.start();
}
return nwLoop;
}
/**
* |