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
018package org.apache.commons.net.tftp;
019
020import java.net.DatagramPacket;
021import 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
047public 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}