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    
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    }