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 }