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    }