    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     * @author Daniel F. Savarese
    043     * @see TFTPPacketException
    044     * @see TFTP
    045     ***/
    046
    047    public abstract class TFTPPacket
    048    {
    049        /***
    050         * The minimum size of a packet.  This is 4 bytes.  It is enough
    051         * to store the opcode and blocknumber or other required data
    052         * depending on the packet type.
    053         ***/
    054        static final int MIN_PACKET_SIZE = 4;
    055
    056        /***
    057         * This is the actual TFTP spec
    058         * identifier and is equal to 1.
    059         * Identifier returned by {@link #getType getType()}
    060         * indicating a read request packet.
    061         ***/
    062        public static final int READ_REQUEST = 1;
    063
    064        /***
    065         * This is the actual TFTP spec
    066         * identifier and is equal to 2.
    067         * Identifier returned by {@link #getType getType()}
    068         * indicating a write request packet.
    069         ***/
    070        public static final int WRITE_REQUEST = 2;
    071
    072        /***
    073         * This is the actual TFTP spec
    074         * identifier and is equal to 3.
    075         * Identifier returned by {@link #getType getType()}
    076         * indicating a data packet.
    077         ***/
    078        public static final int DATA = 3;
    079
    080        /***
    081         * This is the actual TFTP spec
    082         * identifier and is equal to 4.
    083         * Identifier returned by {@link #getType getType()}
    084         * indicating an acknowledgement packet.
    085         ***/
    086        public static final int ACKNOWLEDGEMENT = 4;
    087
    088        /***
    089         * This is the actual TFTP spec
    090         * identifier and is equal to 5.
    091         * Identifier returned by {@link #getType getType()}
    092         * indicating an error packet.
    093         ***/
    094        public static final int ERROR = 5;
    095
    096        /***
    097         * The TFTP data packet maximum segment size in bytes.  This is 512
    098         * and is useful for those familiar with the TFTP protocol who want
    099         * to use the {@link org.apache.commons.net.tftp.TFTP}
    100         * class methods to implement their own TFTP servers or clients.
    101         ***/
    102        public static final int SEGMENT_SIZE = 512;
    103
    104        /*** The type of packet. ***/
    105        int _type;
    106
    107        /*** The port the packet came from or is going to. ***/
    108        int _port;
    109
    110        /*** The host the packet is going to be sent or where it came from. ***/
    111        InetAddress _address;
    112
    113        /***
    114         * When you receive a datagram that you expect to be a TFTP packet, you use
    115         * this factory method to create the proper TFTPPacket object
    116         * encapsulating the data contained in that datagram.  This method is the
    117         * only way you can instantiate a TFTPPacket derived class from a
    118         * datagram.
    119         * <p>
    120         * @param datagram  The datagram containing a TFTP packet.
    121         * @return The TFTPPacket object corresponding to the datagram.
    122         * @exception TFTPPacketException  If the datagram does not contain a valid
    123         *             TFTP packet.
    124         ***/
    125        public final static TFTPPacket newTFTPPacket(DatagramPacket datagram)
    126        throws TFTPPacketException
    127        {
    128            byte[] data;
    129            TFTPPacket packet = null;
    130
    131            if (datagram.getLength() < MIN_PACKET_SIZE)
    132                throw new TFTPPacketException(
    133                    "Bad packet. Datagram data length is too short.");
    134
    135            data = datagram.getData();
    136
    137            switch (data[1])
    138            {
    139            case READ_REQUEST:
    140                packet = new TFTPReadRequestPacket(datagram);
    141                break;
    142            case WRITE_REQUEST:
    143                packet = new TFTPWriteRequestPacket(datagram);
    144                break;
    145            case DATA:
    146                packet = new TFTPDataPacket(datagram);
    147                break;
    148            case ACKNOWLEDGEMENT:
    149                packet = new TFTPAckPacket(datagram);
    150                break;
    151            case ERROR:
    152                packet = new TFTPErrorPacket(datagram);
    153                break;
    154            default:
    155                throw new TFTPPacketException(
    156                    "Bad packet.  Invalid TFTP operator code.");
    157            }
    158
    159            return packet;
    160        }
    161
    162        /***
    163         * This constructor is not visible outside of the package.  It is used
    164         * by subclasses within the package to initialize base data.
    165         * <p>
    166         * @param type The type of the packet.
    167         * @param address The host the packet came from or is going to be sent.
    168         * @param port The port the packet came from or is going to be sent.
    169         **/
    170        TFTPPacket(int type, InetAddress address, int port)
    171        {
    172            _type = type;
    173            _address = address;
    174            _port = port;
    175        }
    176
    177        /***
    178         * This is an abstract method only available within the package for
    179         * implementing efficient datagram transport by elminating buffering.
    180         * It takes a datagram as an argument, and a byte buffer in which
    181         * to store the raw datagram data.  Inside the method, the data
    182         * should be set as the datagram's data and the datagram returned.
    183         * <p>
    184         * @param datagram  The datagram to create.
    185         * @param data The buffer to store the packet and to use in the datagram.
    186         * @return The datagram argument.
    187         ***/
    188        abstract DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data);
    189
    190        /***
    191         * Creates a UDP datagram containing all the TFTP packet
    192         * data in the proper format.
    193         * This is an abstract method, exposed to the programmer in case he
    194         * wants to implement his own TFTP client instead of using
    195         * the {@link org.apache.commons.net.tftp.TFTPClient}
    196         * class.
    197         * Under normal circumstances, you should not have a need to call this
    198         * method.
    199         * <p>
    200         * @return A UDP datagram containing the TFTP packet.
    201         ***/
    202        public abstract DatagramPacket newDatagram();
    203
    204        /***
    205         * Returns the type of the packet.
    206         * <p>
    207         * @return The type of the packet.
    208         ***/
    209        public final int getType()
    210        {
    211            return _type;
    212        }
    213
    214        /***
    215         * Returns the address of the host where the packet is going to be sent
    216         * or where it came from.
    217         * <p>
    218         * @return The type of the packet.
    219         ***/
    220        public final InetAddress getAddress()
    221        {
    222            return _address;
    223        }
    224
    225        /***
    226         * Returns the port where the packet is going to be sent
    227         * or where it came from.
    228         * <p>
    229         * @return The port where the packet came from or where it is going.
    230         ***/
    231        public final int getPort()
    232        {
    233            return _port;
    234        }
    235
    236        /*** Sets the port where the packet is going to be sent. ***/
    237        public final void setPort(int port)
    238        {
    239            _port = port;
    240        }
    241
    242        /*** Sets the host address where the packet is going to be sent. ***/
    243        public final void setAddress(InetAddress address)
    244        {
    245            _address = address;
    246        }
    247    }