Package org.jnode.net.ipv4.udp

Source Code of org.jnode.net.ipv4.udp.UDPHeader

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.net.ipv4.udp;

import org.apache.log4j.Logger;
import org.jnode.net.SocketBuffer;
import org.jnode.net.TransportLayerHeader;
import org.jnode.net.ipv4.IPv4Header;
import org.jnode.net.ipv4.IPv4Utils;
import org.jnode.util.NumberUtils;

/**
* Header of an UDP packet
*
* @author epr
*/
public class UDPHeader implements TransportLayerHeader, UDPConstants {

    /** My logger */
    private static final Logger log = Logger.getLogger(UDPHeader.class);
    /** The port of the sending process or 0 if not used. */
    private final int srcPort;
    /** The destination port within the context of a particular internet address */
    private final int dstPort;
    /** The length in octet. It include the header and the data. Minimum value of the length is 8 */
    private final int udpLength;
   
    private final boolean checksumOk;

    /**
     * Create a new instance
     *
     * @param srcPort The port of the sending process.
     * @param dstPort The destination port.
     * @param dataLength The length of the data.
     */
    public UDPHeader(int srcPort, int dstPort, int dataLength) {
        this.srcPort = srcPort;
        this.dstPort = dstPort;
        this.udpLength = UDP_HLEN + dataLength;
        this.checksumOk = true;
    }

    /**
     * Create a new instance and read the contents from the given buffer
     *
     * @param skbuf The socket buffer.
     */
    public UDPHeader(SocketBuffer skbuf) {
        this.srcPort = skbuf.get16(0);
        this.dstPort = skbuf.get16(2);
        this.udpLength = skbuf.get16(4);
        final int checksum = skbuf.get16(6);
        if (checksum == 0) {
            log.debug("No checksum set");
            this.checksumOk = true;
        } else {
            // Create the pseudo header for checksum calculation
            final IPv4Header ipHdr = (IPv4Header) skbuf.getNetworkLayerHeader();
            final SocketBuffer phdr = new SocketBuffer(12);
            phdr.insert(12);
            ipHdr.getSource().writeTo(phdr, 0);
            ipHdr.getDestination().writeTo(phdr, 4);
            phdr.set(8, 0);
            phdr.set(9, ipHdr.getProtocol());
            phdr.set16(10, udpLength);
            phdr.append(skbuf);
            final int ccs2 = IPv4Utils.calcChecksum(phdr, 0, udpLength + 12);
            this.checksumOk = (ccs2 == 0);
            if (!checksumOk) {
                log.debug("Found invalid UDP checksum 0x" + NumberUtils.hex(ccs2, 4));
            }
        }
    }

    /**
     * @see org.jnode.net.LayerHeader#getLength()
     */
    public int getLength() {
        return UDP_HLEN;
    }

    /**
     * @see org.jnode.net.LayerHeader#prefixTo(org.jnode.net.SocketBuffer)
     */
    public void prefixTo(SocketBuffer skbuf) {
        skbuf.insert(UDP_HLEN);
        skbuf.set16(0, srcPort);
        skbuf.set16(2, dstPort);
        skbuf.set16(4, udpLength);
        skbuf.set16(6, 0); // Checksum, calculate and overwrite later
    }

    /**
     * Finalize the header in the given buffer. This method is called when all
     * layers have set their header data and can be used e.g. to update checksum
     * values.
     *
     * @param skbuf The buffer
     * @param offset The offset to the first byte (in the buffer) of this header
     *            (since low layer headers are already prefixed)
     */
    public void finalizeHeader(SocketBuffer skbuf, int offset) {
        final int ccs = calcChecksum(skbuf, offset);
        skbuf.set16(offset + 6, ccs);
    }

    /**
     * Is the checksum valid?
     */
    public boolean isChecksumOk() {
        return checksumOk;
    }

    /**
     * Gets the destination port
     */
    public int getDstPort() {
        return dstPort;
    }

    /**
     * Gets the source port
     */
    public int getSrcPort() {
        return srcPort;
    }

    /**
     * Gets the length of the UDP packet (header + data)
     */
    public int getUdpLength() {
        return udpLength;
    }

    /**
     * Gets the length of the UDP data.
     */
    public int getDataLength() {
        return udpLength - UDP_HLEN;
    }

    /**
     * @see java.lang.Object#toString()
     */
    public String toString() {
        return "UDP srcPort=" + srcPort + ", dstPort=" + dstPort + ", dataLength=" + getDataLength();
    }

    private int calcChecksum(SocketBuffer skbuf, int offset) {
        final IPv4Header ipHdr = (IPv4Header) skbuf.getNetworkLayerHeader();
        final SocketBuffer phdr = new SocketBuffer(12);
        phdr.insert(12);
        ipHdr.getSource().writeTo(phdr, 0);
        ipHdr.getDestination().writeTo(phdr, 4);
        phdr.set(8, 0);
        phdr.set(9, ipHdr.getProtocol());
        phdr.set16(10, udpLength);
        phdr.append(offset, skbuf);
        final int csLength = udpLength + 12;
        return IPv4Utils.calcChecksum(phdr, 0, csLength);
    }
}
TOP

Related Classes of org.jnode.net.ipv4.udp.UDPHeader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.