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    }