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