/*
* 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_old.Net;
import ejip.jtcpip.util.Debug;
/**
* Represents the UDP transport layer. Contains methods for packet sending and
* receiving to the upper (application) layer and to the lower (network) layer.
*
* @see ejip2.jtcpip.IP
*
* @author Tobias Kellner
* @author Ulrich Feichter
* @author Christof Rath
* @version $Rev: 984 $ $Date: 2009/01/12 23:00:13 $
*/
public class UDP
{
/**
* Send a UDP Packet with the destination IP given as a String.
*
* @param ip
* String containing the destination ip in dotted-decimal format
* @param port
* Destination port
* @param data
* Data to send
* @return Whether sending was successful
* @throws JtcpipException
* IP String is faulty
*/
public static boolean sendPacket(String ip, short port, byte[] data) throws JtcpipException
{
return sendPacket(IP.ipStringToInt(ip), port, data);
}
/**
* Send a UDP Packet with the destination IP given as four bytes.
*
* @param a
* First byte of the destination IP
* @param b
* Second byte of the destination IP
* @param c
* Third byte of the destination IP
* @param d
* Fourth byte of the destination IP String containing the
* destination ip in dotted-decimal format
* @param port
* Destination port
* @param data
* Data to send
* @return Whether sending was successful
*
* @throws JtcpipException
*/
public static boolean sendPacket(byte a, byte b, byte c, byte d, short port, byte[] data)
throws JtcpipException
{
return sendPacket(((a & 0xFF) << 24) + ((b & 0xFF) << 16) + ((c & 0xFF) << 8) + (d & 0xFF),
port, data);
}
/**
* Send a UDP Packet with the destination IP given as an int.
*
* @param remoteIP
* Int containing the destination ip
* @param remotePort
* Destination port
* @param data
* Data to send
* @return Whether sending was successful
*
* @throws JtcpipException
*/
public static boolean sendPacket(int remoteIP, short remotePort, byte[] data)
throws JtcpipException
{
Payload pay = preparePayload(remotePort, (short) 0);
if (pay == null)
return false;
UDPPacket.setData(pay, data);
UDPPacket.setLength(pay, (short) pay.length); // Sets the length in
// the UDP header
if (Debug.enabled)
Debug.println("Trying to send", Debug.DBG_UDP);
IP.asyncSendPayload(pay, remoteIP, IP.PROT_UDP);
return true;
}
/**
* Gets and prepares a UDP Packet with the destination IP given as an int.
*
* @param remotePort
* Destination port
* @param localPort
*
* @return the payload or null
*/
protected static Payload preparePayload(short remotePort, short localPort)
{
Payload pay = Payload.newPayload();
if (pay != null)
{
UDPPacket.setDestPort(pay, remotePort);
UDPPacket.setSourcePort(pay, localPort);
}
return pay;
}
/**
* Receive a packet from the lower (network) Layer.
*
* @param pay
* The packet content
* @see ejip2.jtcpip.IP#handlePayload
*/
public static void receivePayload(Payload pay)
{
if (Debug.enabled)
Debug.println("UDP packed received! ID: ",
Debug.DBG_UDP);
if (!UDPPacket.isChecksumValid(pay))
{
if (Debug.enabled)
Debug.println("Checksum not valid", Debug.DBG_UDP);
Payload.freePayload(pay);
return;
}
UDPConnection conn = UDPConnection.getConnection(pay);
if (conn != null)
{
conn.receivePayload(pay);
Payload.freePayload(pay);
}
else
{
if (IPPacket.getDestAddr(pay) == Net.linkLayer.getIpAddress())
{
if (Debug.enabled)
Debug.println("No matching connection found", Debug.DBG_UDP);
ICMP.sendDestUnreach(pay, 3); // Code 3: port unreachable (see RFC792)
}
else // its a broadcast...
Payload.freePayload(pay);
}
}
}