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 }