    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.net.tftp;
    019
    020    import java.net.DatagramPacket;
    021    import java.net.InetAddress;
    022
    023    /***
    024     * TFTPPacket is an abstract class encapsulating the functionality common
    025     * to the 5 types of TFTP packets.  It also provides a static factory
    026     * method that will create the correct TFTP packet instance from a
    027     * datagram.  This relieves the programmer from having to figure out what
    028     * kind of TFTP packet is contained in a datagram and create it himself.
    029     * <p>
    030     * Details regarding the TFTP protocol and the format of TFTP packets can
    031     * be found in RFC 783.  But the point of these classes is to keep you
    032     * from having to worry about the internals.  Additionally, only very
    033     * few people should have to care about any of the TFTPPacket classes
    034     * or derived classes.  Almost all users should only be concerned with the
    035     * {@link org.apache.commons.net.tftp.TFTPClient} class
    036     * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
    037     * and
    038     * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
    039     * methods.
    040     * <p>
    041     * <p>
    042     * @see TFTPPacketException
    043     * @see TFTP
    044     ***/
    045
    046    public abstract class TFTPPacket
    047    {
    048        /***
    049         * The minimum size of a packet.  This is 4 bytes.  It is enough
    050         * to store the opcode and blocknumber or other required data
    051         * depending on the packet type.
    052         ***/
    053        static final int MIN_PACKET_SIZE = 4;
    054
    055        /***
    056         * This is the actual TFTP spec
    057         * identifier and is equal to 1.
    058         * Identifier returned by {@link #getType getType()}
    059         * indicating a read request packet.
    060         ***/
    061        public static final int READ_REQUEST = 1;
    062
    063        /***
    064         * This is the actual TFTP spec
    065         * identifier and is equal to 2.
    066         * Identifier returned by {@link #getType getType()}
    067         * indicating a write request packet.
    068         ***/
    069        public static final int WRITE_REQUEST = 2;
    070
    071        /***
    072         * This is the actual TFTP spec
    073         * identifier and is equal to 3.
    074         * Identifier returned by {@link #getType getType()}
    075         * indicating a data packet.
    076         ***/
    077        public static final int DATA = 3;
    078
    079        /***
    080         * This is the actual TFTP spec
    081         * identifier and is equal to 4.
    082         * Identifier returned by {@link #getType getType()}
    083         * indicating an acknowledgement packet.
    084         ***/
    085        public static final int ACKNOWLEDGEMENT = 4;
    086
    087        /***
    088         * This is the actual TFTP spec
    089         * identifier and is equal to 5.
    090         * Identifier returned by {@link #getType getType()}
    091         * indicating an error packet.
    092         ***/
    093        public static final int ERROR = 5;
    094
    095        /***
    096         * The TFTP data packet maximum segment size in bytes.  This is 512
    097         * and is useful for those familiar with the TFTP protocol who want
    098         * to use the {@link org.apache.commons.net.tftp.TFTP}
    099         * class methods to implement their own TFTP servers or clients.
    100         ***/
    101        public static final int SEGMENT_SIZE = 512;
    102
    103        /*** The type of packet. ***/
    104        int _type;
    105
    106        /*** The port the packet came from or is going to. ***/
    107        int _port;
    108
    109        /*** The host the packet is going to be sent or where it came from. ***/
    110        InetAddress _address;
    111
    112        /***
    113         * When you receive a datagram that you expect to be a TFTP packet, you use
    114         * this factory method to create the proper TFTPPacket object
    115         * encapsulating the data contained in that datagram.  This method is the
    116         * only way you can instantiate a TFTPPacket derived class from a
    117         * datagram.
    118         * <p>
    119         * @param datagram  The datagram containing a TFTP packet.
    120         * @return The TFTPPacket object corresponding to the datagram.
    121         * @exception TFTPPacketException  If the datagram does not contain a valid
    122         *             TFTP packet.
    123         ***/
    124        public final static TFTPPacket newTFTPPacket(DatagramPacket datagram)
    125        throws TFTPPacketException
    126        {
    127            byte[] data;
    128            TFTPPacket packet = null;
    129
    130            if (datagram.getLength() < MIN_PACKET_SIZE)
    131                throw new TFTPPacketException(
    132                    "Bad packet. Datagram data length is too short.");
    133
    134            data = datagram.getData();
    135
    136            switch (data[1])
    137            {
    138            case READ_REQUEST:
    139                packet = new TFTPReadRequestPacket(datagram);
    140                break;
    141            case WRITE_REQUEST:
    142                packet = new TFTPWriteRequestPacket(datagram);
    143                break;
    144            case DATA:
    145                packet = new TFTPDataPacket(datagram);
    146                break;
    147            case ACKNOWLEDGEMENT:
    148                packet = new TFTPAckPacket(datagram);
    149                break;
    150            case ERROR:
    151                packet = new TFTPErrorPacket(datagram);
    152                break;
    153            default:
    154                throw new TFTPPacketException(
    155                    "Bad packet.  Invalid TFTP operator code.");
    156            }
    157
    158            return packet;
    159        }
    160
    161        /***
    162         * This constructor is not visible outside of the package.  It is used
    163         * by subclasses within the package to initialize base data.
    164         * <p>
    165         * @param type The type of the packet.
    166         * @param address The host the packet came from or is going to be sent.
    167         * @param port The port the packet came from or is going to be sent.
    168         **/
    169        TFTPPacket(int type, InetAddress address, int port)
    170        {
    171            _type = type;
    172            _address = address;
    173            _port = port;
    174        }
    175
    176        /***
    177         * This is an abstract method only available within the package for
    178         * implementing efficient datagram transport by elminating buffering.
    179         * It takes a datagram as an argument, and a byte buffer in which
    180         * to store the raw datagram data.  Inside the method, the data
    181         * should be set as the datagram's data and the datagram returned.
    182         * <p>
    183         * @param datagram  The datagram to create.
    184         * @param data The buffer to store the packet and to use in the datagram.
    185         * @return The datagram argument.
    186         ***/
    187        abstract DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data);
    188
    189        /***
    190         * Creates a UDP datagram containing all the TFTP packet
    191         * data in the proper format.
    192         * This is an abstract method, exposed to the programmer in case he
    193         * wants to implement his own TFTP client instead of using
    194         * the {@link org.apache.commons.net.tftp.TFTPClient}
    195         * class.
    196         * Under normal circumstances, you should not have a need to call this
    197         * method.
    198         * <p>
    199         * @return A UDP datagram containing the TFTP packet.
    200         ***/
    201        public abstract DatagramPacket newDatagram();
    202
    203        /***
    204         * Returns the type of the packet.
    205         * <p>
    206         * @return The type of the packet.
    207         ***/
    208        public final int getType()
    209        {
    210            return _type;
    211        }
    212
    213        /***
    214         * Returns the address of the host where the packet is going to be sent
    215         * or where it came from.
    216         * <p>
    217         * @return The type of the packet.
    218         ***/
    219        public final InetAddress getAddress()
    220        {
    221            return _address;
    222        }
    223
    224        /***
    225         * Returns the port where the packet is going to be sent
    226         * or where it came from.
    227         * <p>
    228         * @return The port where the packet came from or where it is going.
    229         ***/
    230        public final int getPort()
    231        {
    232            return _port;
    233        }
    234
    235        /*** Sets the port where the packet is going to be sent. ***/
    236        public final void setPort(int port)
    237        {
    238            _port = port;
    239        }
    240
    241        /*** Sets the host address where the packet is going to be sent. ***/
    242        public final void setAddress(InetAddress address)
    243        {
    244            _address = address;
    245        }
    246    }